เปรียบเทียบแบบสอบถามที่สองใน SQL Server 2012


14

ฉันกำลังเปรียบเทียบแบบสอบถามที่สองใน SQL Server 2012 เป้าหมายคือการใช้ข้อมูลที่เกี่ยวข้องทั้งหมดที่มีอยู่จากเครื่องมือเพิ่มประสิทธิภาพแบบสอบถามเมื่อเลือกแบบสอบถามที่ดีที่สุด ข้อความค้นหาทั้งสองรายการให้ผลลัพธ์ที่เหมือนกัน ลำดับสูงสุดสำหรับลูกค้าทั้งหมด

การล้างบัฟเฟอร์พูลเสร็จก่อนดำเนินการค้นหาด้วย FREEPROCCACHE และ DROPCLEANBUFFERS

ใช้ข้อมูลที่ให้ไว้ด้านล่างแบบสอบถามใดเป็นตัวเลือกที่ดีกว่า

-- Query 1 - return the maximum order id for a customer
SELECT orderid, custid
FROM Sales.Orders AS O1
WHERE orderid = (SELECT MAX(O2.orderid)
                 FROM Sales.Orders AS O2
                 WHERE O2.custid = O1.custid);


-- Query 2 - return the maximum order id for a customer
SELECT MAX(orderid), custid
FROM Sales.Orders AS O1
group by custid
order by custid

เวลาสถิติ

แบบสอบถาม 1 เวลาสถิติ: เวลา CPU = 0ms, เวลาที่ผ่านไป = 24 ms

แบบสอบถาม 2 เวลาสถิติ: เวลา CPU = 0 ms, เวลาที่ผ่านไป = 23 ms

ข้อมูลสถิติ IO

แบบสอบถาม 1 สถิติ IO: ตาราง 'คำสั่งซื้อ' จำนวนการสแกน 1, การอ่านเชิงตรรกะ 5, การอ่านทางกายภาพ 2, การอ่านล่วงหน้าอ่าน 0, lob ตรรกะอ่าน 0, lob การอ่านทางกายภาพ 0, lob การอ่านล่วงหน้าอ่าน 0

แบบสอบถาม 2 สถิติ IO: ตาราง 'คำสั่งซื้อ' จำนวนการสแกน 1, การอ่านเชิงตรรกะ 4, การอ่านทางกายภาพ 1, การอ่านล่วงหน้าอ่าน 8, lob ตรรกะอ่าน 0, lob การอ่านทางกายภาพ 0, lob การอ่านล่วงหน้าอ่าน 0

แผนการดำเนินการ

ป้อนคำอธิบายรูปภาพที่นี่

เลือกคุณสมบัติ Query 1

ป้อนคำอธิบายรูปภาพที่นี่

คุณสมบัติ SELECT แบบสอบถาม 2

ป้อนคำอธิบายรูปภาพที่นี่

สรุป:

แบบสอบถาม 1

  1. ชุดค่าใช้จ่าย 48%
  2. ตรรกะอ่าน 5
  3. การอ่านทางกายภาพ 2
  4. อ่านล่วงหน้า: 0
  5. เวลา CPU: 0ms
  6. เวลาที่ผ่านไป 24ms
  7. ราคาทรีย่อยโดยประมาณ: 0.0050276
  8. CompileCPU: 2
  9. CompileMemory: 384
  10. CompileTime: 2

แบบสอบถาม 2

  1. ชุดค่าใช้จ่าย 52%
  2. ตรรกะอ่าน 4
  3. การอ่านทางกายภาพ 1
  4. อ่านล่วงหน้า: 8
  5. CPU Time 0
  6. เวลาที่ผ่านไป 23ms
  7. ทรีย่อยโดยประมาณ: 0.0054782
  8. CompileCPU: 0
  9. CompileMemory: 192
  10. CompileTime: 0

โดยส่วนตัวแม้ว่า Query 2 จะมีต้นทุนแบตช์ที่สูงกว่าตามแผนกราฟิก แต่ฉันคิดว่ามันมีประสิทธิภาพมากกว่าที่ Query 1 เนื่องจากแบบสอบถาม 2 ต้องการการอ่านเชิงตรรกะน้อยกว่ามีเวลาที่ลดลงเล็กน้อย compilecpu, compilememory และ compiletime ลดลง การอ่านล่วงหน้าคือ 8 สำหรับแบบสอบถาม 2 และ 0 สำหรับแบบสอบถาม 1

อัปเดต 12:03

นิยามดัชนีแบบคลัสเตอร์

ALTER TABLE [Sales].[Orders] ADD  CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED 
(
    [orderid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

ดัชนีที่ไม่เป็นคลัสเตอร์ idx_nc_custid

CREATE NONCLUSTERED INDEX [idx_nc_custid] ON [Sales].[Orders]
(
    [custid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
พอลไวท์ 9

คำตอบ:


10

ฉันชอบวิธีการของคุณในการพิจารณาอย่างรอบคอบเพื่อปรับแต่งแบบสอบถามและตรวจสอบตัวเลือกและแผนต่างๆ ฉันหวังว่านักพัฒนามากขึ้นทำสิ่งนี้ ข้อควรระวังอย่างหนึ่งคือ - ทดสอบกับแถวจำนวนมากเสมอดูการอ่านแบบลอจิคัลนี่คือตารางเล็ก ๆ ลองและสร้างตัวอย่างโหลดและเรียกใช้แบบสอบถามอีกครั้ง ปัญหาเล็กน้อยหนึ่งข้อ - ในข้อความค้นหายอดนิยมของคุณคุณไม่ได้ขอคำสั่งซื้อจากในข้อความค้นหาด้านล่างของคุณ คุณควรเปรียบเทียบและเปรียบเทียบแต่ละรายการด้วยการสั่งซื้อ

ฉันเพิ่งสร้างตารางคำสั่งขายอย่างรวดเร็วโดยมีคำสั่งขาย 200,000 คำสั่งในนั้น แต่ก็ยังไม่มากนักด้วยจินตนาการ และเรียกใช้แบบสอบถามด้วย ORDER BY ในแต่ละรายการ ฉันยังเล่นกับดัชนีเล็กน้อย

เมื่อไม่มีดัชนีที่คลัสเตอร์ใน OrderID เพียงดัชนีที่ไม่ได้ทำคลัสเตอร์บน CustIDแบบสอบถามที่สองมีประสิทธิภาพสูงกว่า โดยเฉพาะอย่างยิ่งกับการสั่งซื้อโดยรวมอยู่ในแต่ละ มีอยู่สองครั้งที่มีผู้อ่านจำนวนมากในแบบสอบถามแรกกว่าแบบสอบถามที่สองและเปอร์เซ็นต์ค่าใช้จ่ายคือ 67% / 33% ระหว่างแบบสอบถาม

ด้วยดัชนีคลัสเตอร์บน OrderID และดัชนีที่ไม่ใช่คลัสเตอร์เพียง CustIDพวกเขาดำเนินการในความเร็วที่คล้ายกันและจำนวนการอ่านที่แน่นอนเท่ากัน

ดังนั้นฉันขอแนะนำให้คุณเพิ่มจำนวนแถวและทำการทดสอบเพิ่มเติม แต่การวิเคราะห์ขั้นสุดท้ายของฉันในการค้นหาของคุณ -

คุณอาจพบว่าพวกมันมีพฤติกรรมคล้ายกันมากกว่าที่คุณรู้เมื่อคุณเพิ่มแถวดังนั้นโปรดคำนึงถึงข้อแม้นั้นและทดสอบด้วยวิธีนั้น

หากทั้งหมดที่คุณต้องการกลับมาคือ OrderID สูงสุดสำหรับลูกค้าแต่ละรายและคุณต้องการตรวจสอบว่าโดย OrderID นั้นเป็น OrderID ที่ยิ่งใหญ่ที่สุดการสืบค้นที่สองจากทั้งสองนี้เป็นวิธีที่ดีที่สุดที่จะไปจากความคิดของฉัน - มันเป็นบิต ง่ายขึ้นและในขณะที่เคยมีราคาแพงกว่าเล็กน้อยตามราคาทรีย่อยมันเป็นคำสั่งถอดรหัสที่เร็วและง่ายขึ้น หากคุณต้องการเพิ่มคอลัมน์อื่น ๆ ในชุดผลลัพธ์สักวันหนึ่ง จากนั้นแบบสอบถามแรกให้คุณทำเช่นนั้นได้

อัปเดต: หนึ่งในความคิดเห็นของคุณภายใต้คำถามของคุณคือ:

โปรดทราบว่าการค้นหาข้อความค้นหาที่ดีที่สุดในคำถามนี้เป็นวิธีการปรับปรุงเทคนิคที่ใช้ในการเปรียบเทียบ

แต่สิ่งที่ดีที่สุดสำหรับการทดสอบนั้นมีข้อมูลมากขึ้น - ทำให้แน่ใจว่าคุณมีข้อมูลที่สอดคล้องกับการผลิตและการผลิตที่คาดหวังในอนาคต แผนแบบสอบถามเริ่มค้นหาข้อมูลเมื่อคุณให้แถวเพิ่มเติมลงในตารางและพยายามกระจายข้อมูลตามที่คุณคาดหวังในการผลิต และใส่ใจกับสิ่งต่าง ๆ เช่นรวมถึงการสั่งซื้อหรือไม่ที่นี่ฉันไม่คิดว่ามันจะสร้างความแตกต่างเล็กน้อยในตอนท้าย แต่ก็ยังคุ้มค่าที่จะขุด

วิธีการเปรียบเทียบรายละเอียดและข้อมูลระดับนี้เป็นวิธีที่ดี ค่าใช้จ่ายย่อยนั้นโดยพลการและไม่มีความหมายส่วนใหญ่ แต่ก็ยังคุ้มค่าอย่างน้อยที่จะดูเพื่อเปรียบเทียบระหว่างการแก้ไข / การเปลี่ยนแปลงหรือแม้กระทั่งระหว่างการสืบค้น การดูสถิติเวลาและ IO มีความสำคัญเช่นเดียวกับการดูแผนสำหรับสิ่งใดก็ตามที่รู้สึกไม่เหมาะสมกับขนาดของข้อมูลที่คุณกำลังทำงานและสิ่งที่คุณพยายามทำ


สวัสดีอีกครั้งขอขอบคุณสำหรับคะแนนของคุณเกี่ยวกับการใช้ข้อมูลจำนวนมาก นี่ไม่ใช่ครั้งแรกที่มีคนนำมันขึ้นมา ครั้งสุดท้ายที่ต้องพิจารณาการแตกแฟรกเมนต์ที่เป็นไปได้จากการแยกหน้า ในตัวอย่างแถว 200,000 ของคุณคุณตรวจสอบการกระจายตัวหรือไม่
Craig Efrein

ในตัวอย่างแถวขนาดเล็ก 200k ที่รวดเร็วของฉันฉันไม่ได้มุ่งเน้นไปที่การแยกส่วนไม่ แต่วิธีที่ฉันทำมันจะไม่มีเลย ฉันสร้างตารางเติมข้อมูลแล้วสร้างดัชนีดังนั้นพวกเขาจึงเป็นดัชนีที่สร้างขึ้นใหม่ และนั่นจะไม่เปลี่ยนวิธีการดูแผนแบบสอบถามซึ่งดูเหมือนจะเป็นคำถามหลัก ปริมาณข้อมูลมีขนาดใหญ่มากจริงๆเมื่อดูแผนการสืบค้นอย่างถูกต้อง ฉันมักจะเห็นกรณีที่มันดูดีใน dev (มี 1-10 แถว) และเป็นที่น่ากลัวในแยงกับข้อมูลจริง แต่วิธีการของคุณดีและหวังว่าข้อมูลนี้และการสนทนาในความคิดเห็นจะช่วยได้
Mike Walsh

เนื่องจากเราจัดกลุ่มโดย custid คุณทำให้ค่า custid สุ่มอย่างไรพอ? สิ่งหนึ่งที่ฉันจำได้จากการอ่านของฉันคือความสำคัญของค่านิยมที่แตกต่าง หาก custid มีลูกค้าจำนวนน้อยรายเท่านั้นค่าใช้จ่ายสำหรับการรวมสตรีมจะไม่เป็นจริง
Craig Efrein

ฉันเพิ่งใช้ฟังก์ชั่น RAND เพื่อสร้างลูกค้า 100 รายและกำหนดหนึ่งรายการให้กับคำสั่งซื้อแต่ละรายการโดยสุ่มฉันทำการตรวจสอบอย่างรวดเร็ว :)
Mike Walsh

ขอบคุณไมค์สำหรับความช่วยเหลือของคุณ หนึ่งคำถามสุดท้ายว่า จากหน้าจอคุณสมบัติ SELECT จากแผนปฏิบัติการในปี 2012 ที่ฉันให้ไว้ในคำถามของฉันคุณสนใจค่าอะไร
Craig Efrein
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.