ไม่มีดัชนีที่ไม่ได้ทำคลัสเตอร์เป็นส่วนหนึ่งของดัชนีที่ทำคลัสเตอร์แล้ว


9

ฉันกำลังดีบักเคียวรีที่รันช้าและในแผนการดำเนินการขอแนะนำให้ใช้ดัชนีที่ไม่ใช่คลัสเตอร์โดยมีผลกระทบ 51.6648 อย่างไรก็ตามดัชนีที่ไม่ทำคลัสเตอร์จะมีเฉพาะคอลัมน์ที่อยู่ในดัชนีคอมโพสิตคีย์หลัก (PK) แล้วเท่านั้น

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

นอกจากนี้ดัชนีที่ไม่ทำคลัสเตอร์จะมีคอลัมน์ PK สองในสามเท่านั้นโดยที่คอลัมน์ที่สามนั้นถูกเพิ่มเป็นคอลัมน์ที่รวมไว้ เป็นincludeอีกสาเหตุหนึ่งที่ทำไมการใช้ดัชนีที่ไม่ทำคลัสเตอร์อาจจะดีที่สุด?

ด้านล่างเป็นตัวอย่างของโครงสร้างตารางที่ฉันทำงานด้วย:

Tables-

Retailers (
    RetailerID int PK, 
    name ...)

Retailer_Relation_Types (
    RelationType smallint PK, 
    Description nvarchar(50) ...)

Retailer_Relations (
    RetailerID int PK FK, 
    RelatedRetailerID int PK FK, 
    RelationType smallint PK FK, 
    CreatedOn datetime ...)

ตารางRetailer_Relationsมีดัชนีคอมโพสิต PK ต่อไปนี้และดัชนีแนะนำ

CONSTRAINT PK_Retailer_Relations 
PRIMARY KEY CLUSTERED (
    RetailerID ASC, 
    RelatedRetailerID ASC, 
    RelationType ASC
    ) ON [PRIMARY]

CREATE NONCLUSTERED INDEX <NameOfIndex> 
ON Retailer_Relations (
    RetailerID, 
    RelationType
    ) 
INCLUDE (
    RelatedRetailerID
    )

คำตอบ:


12

ตาราง Retailer_Relations มีดัชนีคอมโพสิต PK ต่อไปนี้และดัชนีแนะนำ

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

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

เป็นผลให้พวกเขาอาจผิดมาก หากคุณไม่แน่ใจว่าจะช่วยได้อย่างไรสิ่งที่ดีที่สุดที่ควรทำคือทดสอบสถานการณ์ก่อนและหลัง คุณสามารถทำได้โดยเพิ่มคำสั่ง SET STATISTICS IO, TIME ON;ก่อนเรียกใช้แบบสอบถาม

นอกจากนี้คุณสามารถใช้ตัวแยกวิเคราะห์สถิติเพื่อให้ง่ายต่อการอ่านสถิติเหล่านี้

อาจเป็นเพราะลำดับของคอลัมน์ในดัชนีหรือไม่

ถูกต้องการสร้างดัชนีที่ขาดหายไปสามารถปรับปรุงการเลือกในการสืบค้นตัวอย่างเช่นหากแบบสอบถามของคุณมีลักษณะดังนี้:

SELECT  RelatedRetailerID
FROM Retailer_Relations 
WHERE
RetailerID = 5 AND
RelationType = 20;

หรือเช่นนี้

SELECT  RelatedRetailerID
FROM Retailer_Relations 
ORDER BY
RetailerID,
RelationType;

เหตุผลที่อยู่เบื้องหลังนี้คือดัชนีทั้งสองสามารถค้นหาใน RetailerID ส่วนนั้นจะไม่เปลี่ยนแปลง แต่ถ้าใช้ตัวกรอง / การสั่งซื้อพิเศษใน RelationType ล่ะ มันจะอยู่เหนือตำแหน่งในดัชนีคลัสเตอร์เนื่องจากเป็นค่าคีย์ที่สามไม่ใช่ค่าคีย์ที่สอง และอย่างที่เรารู้มันเป็นค่าคีย์ที่สองใน NCI

โอเค แต่ดัชนีที่ไม่คลัสเตอร์จะปรับปรุงแบบสอบถามเมื่อใดหรืออย่างไร

สองสามกรณีอาจเป็น:

  • ถ้าประเภทความสัมพันธ์กรองค่าจำนวนมาก I / O ที่เหลืออาจสูงซึ่งส่งผลให้ต้องการดัชนีที่ไม่ใช่คลัสเตอร์ (Query # 1) ที่เป็นไปได้
  • การสั่งซื้อสองคอลัมน์เกิดขึ้น (ทางเดียว) และชุดผลลัพธ์มีขนาดใหญ่ (แบบสอบถาม # 2)
  • ดังที่ @AaronBertrand กล่าวถึง: หากความแตกต่างของขนาด CI เทียบกับ NCI เป็นจำนวนมากการเพิ่ม NCI จะช่วยลดหน้าที่อ่านโดยการสืบค้นที่ได้รับประโยชน์

หมายเหตุข้าง NCI

ในฐานะที่เป็นหมายเหตุด้านข้างการเพิ่มคอลัมน์คีย์ในรายการรวมใน NCI ของคุณจึงไม่จำเป็นอย่างแน่นอนเนื่องจากคอลัมน์คีย์ CI จะรวมอยู่ในดัชนีที่ไม่ใช่คลัสเตอร์ทั้งหมดโดยอัตโนมัติ

คุณสามารถเลือกที่จะทำเช่นนั้นหากคุณไม่แน่ใจว่าดัชนีกลุ่มจะยังคงเหมือนเดิมหรือไม่และต้องการให้คอลัมน์นั้นรวมอยู่ด้วยเสมอ

หากคุณเพิ่มแผนการดำเนินการผ่าน PasteThePlanเราสามารถให้ข้อมูลเพิ่มเติมเกี่ยวกับการจัดทำดัชนี / ปรับปรุงแบบสอบถาม


การทดสอบ

สร้างตารางและเพิ่มบางแถว

CREATE TABLE Retailer_Relations (
    RetailerID int , 
    RelatedRetailerID int , 
    RelationType smallint, 
    CreatedOn datetime,
    CONSTRAINT PK_Retailer_Relations 
PRIMARY KEY CLUSTERED (
    RetailerID ASC, 
    RelatedRetailerID ASC, 
    RelationType ASC
    ) ON [PRIMARY])


    DECLARE @I Int = 1
    WHILE @I < 1000
    BEGIN
    INSERT INTO Retailer_Relations(RetailerID,RelatedRetailerID,RelationType,CreatedOn)
    VALUES(@I,@I,@I,GETDATE()
    )
    set @I += 1
    END

ข้อความค้นหา # 1

    SELECT  RelatedRetailerID
FROM Retailer_Relations 
WHERE
RetailerID = 5 AND
RelationType = 20;

วางแผนโดยไม่มีดัชนีที่นี่

ในขณะที่กำลังทำการค้นหามันกำลังทำการค้นหาบน RetailerID หลังจากนั้นจะมีการออกคำสั่ง I / O ที่เหลือบน RelationType

เพิ่มดัชนี

CREATE NONCLUSTERED INDEX IX_TEST
ON Retailer_Relations (
    RetailerID, 
    RelationType
    ) 
INCLUDE (
    RelatedRetailerID
    )

เพรดิเคตที่เหลือจะหายไปทุกอย่างเกิดขึ้นในเพรดิเคตค้นหาทั้งสองคอลัมน์

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

ด้วยการสืบค้นครั้งที่สองความช่วยเหลือของดัชนีที่เพิ่มเข้ามานั้นชัดเจนยิ่งขึ้น:

SELECT  RelatedRetailerID
FROM Retailer_Relations 
ORDER BY
RetailerID,
RelationType;

วางแผนโดยไม่มีดัชนีด้วยตัวดำเนินการเรียง:

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

วางแผนกับดัชนีโดยใช้ดัชนีลบตัวดำเนินการเรียงลำดับ

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


1
ขอบคุณ Randi ฉันจะทำเครื่องหมายสิ่งนี้เป็นคำตอบ แต่คุณต้องการถามว่าคำแนะนำดัชนีที่หายไปนั้นเป็นไปตามแผนดำเนินการโดยประมาณหรือไม่ ฉันถามสิ่งนี้ตามที่ปรากฏในแผนปฏิบัติการจริงใน SS2016
Fletch

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