แผนการดำเนินการไม่ได้ใช้ INDEX แต่ใช้การสแกนตาราง


9

ฉันรู้ว่าเมื่อใช้ดัชนีหรือการสแกนตาราง SQL Server จะใช้สถิติเพื่อดูว่าอันไหนดีกว่า

ฉันมีตารางที่มี 20 ล้านแถว ฉันมีดัชนีใน (SnapshotKey, การวัด) และแบบสอบถามนี้:

select Measure, SnapshotKey, MeasureBand
from t1
where Measure = 'FinanceFICOScore'
group by Measure, SnapshotKey, MeasureBand

แบบสอบถามส่งคืนแถว 500k ดังนั้นแบบสอบถามจึงเลือกเพียง 2.5% ของแถวของตาราง

คำถามคือทำไม SQL Server ไม่ใช้ดัชนี nonclustered ฉันมีและใช้การสแกนตารางแทน?

มีการอัพเดทสถิติ

ดีที่จะพูดถึงว่าประสิทธิภาพของแบบสอบถามนั้นดี

สแกนตาราง

สแกนตาราง

ดัชนีบังคับ

ดัชนีบังคับ

โครงสร้างตาราง / ดัชนี

CREATE TABLE [t1](
    [SnapshotKey] [int] NOT NULL,
    [SnapshotDt] [date] NOT NULL,
    [Measure] [nvarchar](30) NOT NULL,
    [MeasureBand] [nvarchar](30) NOT NULL,
    -- and many more fields
) ON [PRIMARY]

ไม่มี PK บนโต๊ะเนื่องจากเป็นคลังข้อมูล

CREATE NONCLUSTERED INDEX [nci_SnapshotKeyMeasure] ON [t1]
(
    [SnapshotKey] ASC,
    [Measure] ASC
)

คำตอบ:


16

การค้นหาดัชนีอาจไม่ใช่ตัวเลือกที่ดีที่สุดหากคุณส่งคืนแถวจำนวนมากและ / หรือแถวกว้างมาก การค้นหาอาจมีราคาแพงหากดัชนีของคุณไม่ครอบคลุม ดู # 2 ที่นี่

ในสถานการณ์ของคุณเครื่องมือเพิ่มประสิทธิภาพการสืบค้นประมาณการว่าการค้นหา 50,000 รายการที่ค้นหาจะมีราคาแพงกว่าการสแกนครั้งเดียว ตัวเลือกของเครื่องมือเพิ่มประสิทธิภาพระหว่างการสแกนและการค้นหา (ด้วยการค้นหา RID สำหรับคอลัมน์ที่ต้องการโดยแบบสอบถาม แต่ไม่มีอยู่ในดัชนีที่ไม่ใช่คลัสเตอร์) ขึ้นอยู่กับต้นทุนโดยประมาณของแต่ละทางเลือก

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

ตอนนี้แบบจำลองต้นทุนที่ใช้โดยเครื่องมือเพิ่มประสิทธิภาพจะขึ้นอยู่กับสมมติฐานและ "หมายเลขมายากล" ที่ไม่น่าจะตรงกับคุณลักษณะประสิทธิภาพของระบบของคุณ โดยเฉพาะอย่างยิ่งสมมติฐานหนึ่งที่ทำในรูปแบบคือแบบสอบถามเริ่มดำเนินการโดยไม่มีหน้าข้อมูลหรือดัชนีที่ต้องการในหน่วยความจำ อีกอย่างคือลำดับ I / O (คาดว่าจะสแกน) มีราคาถูกกว่ารูปแบบ I / O แบบสุ่มที่สันนิษฐานสำหรับ RID Lookups มีข้อสันนิษฐานและคำเตือนอื่น ๆ อีกมากมายที่มากเกินไปที่จะกล่าวถึงในรายละเอียดที่นี่

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

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


9

คุณมีแถวที่ตรงกัน 595,947 แถวซึ่งประมาณ 3% ของข้อมูลของคุณ ดังนั้นราคาของการค้นหาจึงเพิ่มขึ้นอย่างรวดเร็ว สมมติว่าคุณมี 100 แถวต่อหน้าในตารางของคุณนั่นคือ 200,000 หน้าสำหรับอ่านในการสแกนตาราง นั่นถูกกว่าการค้นหา 595,947 ครั้งมาก

ด้วยGROUP BYประโยคในคำถามฉันคิดว่าคุณจะดีกว่าด้วยคีย์ผสมบน (การวัด SnapshotKey, MeasureBand)

ดูคำแนะนำ "ดัชนีหายไป" มันบอกให้คุณรวมคอลัมน์เพื่อหลีกเลี่ยงการค้นหา โดยทั่วไปหากคุณอ้างอิงคอลัมน์อื่น ๆ ในการสืบค้นของคุณพวกเขาจะต้องอยู่ในคีย์หรือINCLUDEส่วนของดัชนีใหม่ มิฉะนั้นจะต้องทำการค้นหา 595,947 รายการเพื่อรับค่าเหล่านั้น

ตัวอย่างเช่นสำหรับแบบสอบถาม:

select Measure, SnapshotKey, MeasureBand, SUM(NumLoans), SUM(PrinBal)
from t1
where Measure = 'FinanceFICOScore'
group by Measure, SnapshotKey, MeasureBand

... คุณจะต้อง:

CREATE INDEX ixWhatever 
ON t1 (Measure, SnapshotKey, MeasureBand) 
INCLUDE (NumLoans,PrinBal);

6
  1. ฟิลด์ในเงื่อนไข WHERE ของคุณไม่ใช่ฟิลด์นำของดัชนี

  2. คุณได้measureกำหนดให้เป็น NVARCHAR ดังนั้นคำนำหน้าตัวอักษรที่มี:N where Measure = N'FinanceFICOScore'

SnapshotKeyพิจารณาการสร้างดัชนีคลัสเตอร์บน ถ้ามันไม่ซ้ำกันก็สามารถ PK (และ Clustered) หากไม่ซ้ำกันจะไม่สามารถเป็น PK ได้ แต่ยังสามารถเป็นดัชนีที่ไม่ซ้ำกันได้ ดังนั้นดัชนีที่ไม่ใช่คลัสเตอร์ของคุณจะอยู่ในmeasureคอลัมน์เท่านั้น

และพิจารณาว่าฟิลด์แรกในGROUP BYนี้ยังมีmeasureที่ยังจะได้รับประโยชน์จากการมีmeasureเป็นข้อมูลชั้นนำ

ในความเป็นจริงสำหรับการดำเนินการนี้คุณอาจต้องกำหนดดัชนีที่ไม่ใช่แบบไม่Measure, SnapshotKey, MeasureBandรวมกลุ่มในลำดับที่แน่นอนนั้นเนื่องจากตรงกับGROUP BYส่วน ขนาดที่เพิ่มจริง ๆ เท่านั้นMeasureBandเนื่องจากดัชนี NonClustered นั้นมีพื้นฐานอยู่Measureแล้วและMeasureKeyรวมอยู่ในดัชนีแล้วเนื่องจากเป็นคีย์ดัชนีแบบคลัสเตอร์ (ไม่ใช่Measureจะไม่ซ้ำกันในดัชนี NonClustered)

@ Rob ได้กล่าวถึงในความคิดเห็นนี้ถูกลบในคำตอบของเขาว่าการแก้ปัญหานี้ต้องมีเพียงว่าดัชนี nonclustered ถูกกำหนดด้วยทั้งสามเขตข้อมูลในคำสั่งนี้และว่าการสร้างคลัสเตอร์ (ที่ไม่ซ้ำกัน) ดัชนีในการSnapshotKeyไม่ได้เป็นสิ่งที่จำเป็น ในขณะที่เขาอาจจะถูกต้อง (ฉันหวังว่าจะทำงานได้น้อยลง) ฉันยังคงยืนยันว่าการมีดัชนีแบบกลุ่มนั้นมีประโยชน์ไม่เพียงแค่การดำเนินการนี้ แต่อาจเป็นเรื่องอื่น


การอภิปรายในคำตอบนี้ได้รับการย้ายไปแชท
Paul White 9
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.