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


11

รับตัวอย่างถัดไป:

IF OBJECT_ID('dbo.my_table') IS NOT NULL
    DROP TABLE [dbo].[my_table];
GO

CREATE TABLE [dbo].[my_table]
(
    [id]    int IDENTITY (1,1)  NOT NULL PRIMARY KEY,
    [foo]   int                 NULL,
    [bar]   int                 NULL,
    [nki]   int                 NOT NULL
);
GO

/* Insert some random data */
INSERT INTO [dbo].[my_table] (foo, bar, nki)
SELECT TOP (100000)
    ABS(CHECKSUM(NewId())) % 14,
    ABS(CHECKSUM(NewId())) % 20,
    n = CONVERT(INT, ROW_NUMBER() OVER (ORDER BY s1.[object_id]))
FROM 
    sys.all_objects AS s1 
CROSS JOIN 
    sys.all_objects AS s2
GO

CREATE UNIQUE NONCLUSTERED INDEX [IX_my_table]
    ON [dbo].[my_table] ([nki] ASC);
GO

ถ้าฉันดึงระเบียนทั้งหมดที่เรียงลำดับโดย[nki](ดัชนีที่ไม่ใช่คลัสเตอร์):

SET STATISTICS TIME ON;
SELECT id, foo, bar, nki FROM my_table ORDER BY nki;
SET STATISTICS TIME OFF;

SQL Server Execution Times: CPU time = 266 ms, elapsed time = 493 ms

เครื่องมือเพิ่มประสิทธิภาพเลือกดัชนีคลัสเตอร์จากนั้นใช้อัลกอริทึมการเรียงลำดับ

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

Execution plan

แต่ถ้าฉันบังคับให้ใช้ดัชนีที่ไม่ใช่คลัสเตอร์:

SET STATISTICS TIME ON;
SELECT id, foo, bar, nki FROM my_table WITH(INDEX(IX_my_TABLE));
SET STATISTICS TIME OFF;

SQL Server Execution Times: CPU time = 311 ms, elapsed time = 188 ms

จากนั้นจะใช้ดัชนีที่ไม่คลัสเตอร์กับการค้นหาคีย์:

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

Execution plan

เห็นได้ชัดว่าหากดัชนีที่ไม่ใช่คลัสเตอร์ถูกเปลี่ยนเป็นดัชนีครอบคลุม:

CREATE UNIQUE NONCLUSTERED INDEX [IX_my_table]
    ON [dbo].[my_table] ([nki] ASC)
    INCLUDE (id, foo, bar);
GO

จากนั้นจะใช้เฉพาะดัชนีนี้:

SET STATISTICS TIME ON;
SELECT id, foo, bar, nki FROM my_table ORDER BY nki;
SET STATISTICS TIME OFF;

SQL Server Execution Times: CPU time = 32 ms, elapsed time = 106 ms

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

Execution plan


คำถาม

  • เหตุใด SQL Server จึงใช้ดัชนีคลัสเตอร์รวมถึงอัลกอริทึมการเรียงลำดับแทนที่จะใช้ดัชนีที่ไม่ใช่คลัสเตอร์แม้ว่าเวลาดำเนินการจะเร็วขึ้น 38% ในกรณีหลัง

1
คุณตั้งใจจะออกจากคำสั่ง ORDER BY ในการสืบค้นดัชนีบังคับหรือไม่?
Forrest

คำตอบ:


9

เหตุใด SQL Server จึงใช้ดัชนีคลัสเตอร์รวมถึงอัลกอริทึมการเรียงลำดับแทนที่จะใช้ดัชนีที่ไม่ใช่คลัสเตอร์แม้ว่าเวลาดำเนินการจะเร็วขึ้น 38% ในกรณีหลัง

เนื่องจาก SQL Server ใช้เครื่องมือเพิ่มประสิทธิภาพราคาตามสถิติไม่ใช่ข้อมูลรันไทม์

ในระหว่างกระบวนการประเมินค่าใช้จ่ายสำหรับแบบสอบถามนี้จริง ๆ แล้วประเมินแผนการค้นหา แต่ประมาณการจะใช้ความพยายามมากขึ้น (โปรดทราบว่า "ต้นทุน Subtree โดยประมาณ" เมื่อโฮเวอร์เหนือ SELECT ในแผนการดำเนินการ) ไม่จำเป็นต้องมีสมมติฐานที่ไม่ดีเช่นกัน - บนเครื่องทดสอบของฉันแผนการค้นหาใช้ 6X CPU ของการเรียงลำดับ / สแกน

มองหาคำตอบของ Rob Farley ว่าเหตุใด SQL Server อาจเสียค่าใช้จ่ายในการวางแผนการค้นหาที่สูงขึ้น


9

หากคุณต้องเปรียบเทียบจำนวนการอ่านที่ต้องการในการค้นหา 100,000 ครั้งกับสิ่งที่เกี่ยวข้องกับการเรียงลำดับคุณอาจได้รับแนวคิดอย่างรวดเร็วว่าทำไม Query Optimizer ถึงตัวเลขที่ CIX + Sort เป็นตัวเลือกที่ดีที่สุด

การดำเนินการค้นหาจบลงด้วยความรวดเร็วเพราะหน้าเว็บที่กำลังอ่านอยู่ในหน่วยความจำ (แม้ว่าคุณจะล้างแคชคุณมีจำนวนแถวต่อหน้าดังนั้นคุณจึงอ่านหน้าเดียวกันซ้ำแล้วซ้ำอีก แต่มีการแตกแฟรกเมนต์แตกต่างกัน หรือแรงกดดันหน่วยความจำที่แตกต่างจากกิจกรรมอื่นซึ่งอาจไม่เป็นเช่นนั้น) การใช้ CIX + Sort ไปเร็วกว่าจริงๆ แต่สิ่งที่คุณเห็นคือเพราะต้นทุนของการอ่านไม่ได้คำนึงถึงความเลวของการกดปุ่มหน้าซ้ำ ๆ


4

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

ตามที่แนะนำต่อความคิดเห็นโดยJohn Eisbrenerหนึ่งในผู้อ้างอิงมากที่สุดแม้ในบล็อกอื่น ๆ บทความนี้น่าสนใจของ Kimberly L. Tripp:

แต่มันไม่ได้เป็นเพียงสิ่งเดียวหากคุณสนใจคุณสามารถดูที่หน้านี้:

อย่างที่คุณเห็นพวกมันทั้งหมดเคลื่อนไปรอบ ๆ แนวคิดของจุดเปลี่ยน

อ้างอิงจากบทความ KL Tripp

จุดเปลี่ยนคืออะไร?

เป็นจุดที่จำนวนแถวที่ส่งคืนคือ " ไม่เลือกเพียงพอ " SQL Server เลือกที่จะไม่ใช้ดัชนีที่ไม่ทำคลัสเตอร์เพื่อค้นหาแถวข้อมูลที่เกี่ยวข้องและทำการสแกนตารางแทน

เมื่อ SQL Server ใช้ดัชนีที่ไม่ทำคลัสเตอร์บนฮีปโดยทั่วไปจะได้รับรายการพอยน์เตอร์ไปยังหน้าของตารางฐาน จากนั้นจะใช้ตัวชี้เหล่านี้เพื่อดึงข้อมูลแถวด้วยชุดการปฏิบัติการที่เรียกว่า Row ID Lookups (RID) ซึ่งหมายความว่าอย่างน้อยมันจะใช้เป็นจำนวนหน้าอ่านตามจำนวนแถวที่ส่งคืนและอาจมากกว่านี้ กระบวนการค่อนข้างคล้ายกับดัชนีคลัสเตอร์เป็นตารางฐานผลลัพธ์เดียวกันอ่านเพิ่มเติม

แต่เมื่อถึงจุดเปลี่ยนที่เกิดขึ้น?

แน่นอนที่สุดในชีวิตนี้มันขึ้นอยู่กับ ...

ไม่จริงจังมันเกิดขึ้นระหว่าง 25% ถึง 33% ของจำนวนหน้าในตารางขึ้นอยู่กับจำนวนแถวต่อหน้า แต่มีปัจจัยอื่น ๆ อีกมากมายที่คุณควรพิจารณา:

อ้างถึงจากบทความ ITPRoToday

ปัจจัยอื่น ๆ ที่มีผลต่อ Tipping Point แม้ว่าค่าใช้จ่ายของการค้นหา RID นั้นเป็นปัจจัยที่สำคัญที่สุดที่มีผลต่อการให้ทิป แต่ก็มีปัจจัยอื่น ๆ อีกมากมาย:

  • I / O ทางกายภาพมีประสิทธิภาพมากขึ้นเมื่อสแกนดัชนีคลัสเตอร์ ข้อมูลดัชนีแบบคลัสเตอร์จะถูกวางเรียงตามลำดับบนดิสก์ตามลำดับดัชนี ดังนั้นจึงมีหัวด้านข้างเดินทางน้อยมากบนดิสก์ซึ่งช่วยเพิ่มประสิทธิภาพ I / O
  • เมื่อเอ็นจิ้นฐานข้อมูลกำลังสแกนดัชนีคลัสเตอร์มันรู้ว่ามีความเป็นไปได้สูงที่หน้าต่อไปของดิสก์แทร็กจะยังคงมีข้อมูลที่ต้องการ ดังนั้นจึงเริ่มอ่านล่วงหน้าในชุด 64KB แทนที่จะเป็นหน้า 8KB ปกติ ซึ่งจะส่งผลให้ I / O เร็วขึ้น

ตอนนี้ถ้าฉันรันคำสั่งของฉันอีกครั้งโดยใช้สถิติ IO:

SET STATISTICS IO ON;
SELECT id, foo, bar, nki FROM my_table WHERE nki < 20000 ORDER BY nki ;
SET STATISTICS IO OFF;

Logical reads: 312

SET STATISTICS IO ON;
SELECT id, foo, bar, nki FROM my_table WITH(INDEX(IX_my_TABLE));
SET STATISTICS IO OFF;

Logical reads: 41293

แบบสอบถามที่สองต้องการอ่านเชิงตรรกะมากกว่าแบบสอบถามแรก

ฉันควรหลีกเลี่ยงดัชนีที่ไม่ทำคลัสเตอร์หรือไม่?

ไม่ได้ดัชนีคลัสเตอร์อาจมีประโยชน์ แต่คุ้มค่ากับการใช้เวลาและพยายามวิเคราะห์สิ่งที่คุณพยายามทำให้สำเร็จเป็นพิเศษ

อ้างอิงจากบทความ KL Tripp

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

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

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