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


12

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

แบบสอบถามนี้ทำงานในประมาณ 2.5 วินาที:

SELECT TOP 1000 * FROM [CIA_WIZ].[dbo].[Heartbeats]
WHERE [DateEntered] BETWEEN '2011-08-30' and '2011-08-31';

อันนี้ทำงานในประมาณ 33ms:

SELECT TOP 1000 * FROM [CIA_WIZ].[dbo].[Heartbeats]
WHERE [DateEntered] BETWEEN '2011-08-30' and '2011-08-31' 
ORDER BY [DateEntered], [DeviceID];

มีดัชนีคลัสเตอร์ในฟิลด์ [ID] (pk) และมีดัชนีที่ไม่ใช่คลัสเตอร์ใน [DateEntered], [DeviceID] แบบสอบถามแรกใช้ดัชนีคลัสเตอร์แบบสอบถามที่สองใช้ดัชนีที่ไม่ใช่คลัสเตอร์ของฉัน คำถามของฉันคือสองส่วน:

  • ทำไมเนื่องจากแบบสอบถามทั้งสองมีส่วนคำสั่ง WHERE ในฟิลด์ [DateEntered] เซิร์ฟเวอร์จึงใช้ดัชนีคลัสเตอร์ในครั้งแรก แต่ไม่ใช่อันดับที่สองหรือไม่
  • ฉันจะทำให้ดัชนีที่ไม่ใช่แบบคลัสเตอร์นั้นถูกใช้เป็นค่าเริ่มต้นในแบบสอบถามนี้ได้โดยไม่ต้องสั่งซื้อ (หรือเพราะเหตุใดฉันจึงไม่ต้องการพฤติกรรมนั้น)

DateEntered เป็น DateTime ในกรณีนี้ฉันใช้ส่วนวันที่ แต่บางครั้งฉันก็ค้นหาทั้งวันและเวลาด้วยกัน
เนท

คำตอบ:


9

แบบสอบถามแรกจะสแกนตารางตามเกณฑ์ที่ฉันอธิบายไว้ก่อนหน้าใน: เป็นไปได้หรือไม่ที่จะเพิ่มประสิทธิภาพการสืบค้นในตารางแคบ ๆ ที่มีแถวนับล้านแถว

(เป็นไปได้ว่าข้อความค้นหาของคุณที่ไม่มีส่วนTOP 1000คำสั่งจะส่งคืนแถวมากกว่า 46k หรือบางตำแหน่งระหว่าง 35k ถึง 46k (พื้นที่สีเทา ;-))

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

กลับลำดับของคอลัมน์ในส่วนORDER BYคำสั่งและคุณกลับไปที่การสแกนดัชนีแบบกลุ่มเนื่องจาก NC INDEX นั้นไม่มีประโยชน์

แก้ไขลืมคำตอบสำหรับคำถามที่สองทำไมคุณไม่ต้องการสิ่งนี้

การใช้ดัชนีที่ไม่ครอบคลุมที่ไม่ใช่คลัสเตอร์หมายความว่า rowID ถูกค้นหาในดัชนี NC และคอลัมน์ที่หายไปจะต้องค้นหาในดัชนีคลัสเตอร์ (ดัชนีคลัสเตอร์ที่มีคอลัมน์ทั้งหมดของตาราง) IO's เพื่อค้นหาคอลัมน์ที่หายไปในดัชนีคลัสเตอร์คือ Random IOs

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

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

ในกรณีของคุณเครื่องมือเพิ่มประสิทธิภาพจะตัดสินใจระหว่างแถว 35k และ 46k ซึ่งมีราคาไม่แพงเมื่อเทียบกับการสแกนดัชนีแบบกลุ่ม ใช่มันผิด และในหลายกรณีที่มีการทำดัชนีไม่ใช่กลุ่มแคบ ๆ ไม่ให้เลือกWHEREคำสั่งหรือตารางขนาดใหญ่สำหรับเรื่องนี้สิ่งนี้ผิดพลาด (โต๊ะของคุณแย่กว่าเดิมเพราะมันเป็นตารางที่แคบมากเช่นกัน)

ตอนนี้การเพิ่มORDER BYทำให้การสแกนดัชนีแบบคลัสเตอร์นั้นมีราคาแพงกว่าจากนั้นเรียงลำดับผลลัพธ์ แต่เครื่องมือเพิ่มประสิทธิภาพจะถือว่าถูกกว่าที่จะใช้ดัชนี NC ที่สั่งซื้อทั้งหมดแล้วจ่ายค่าปรับ IO แบบสุ่มสำหรับการค้นหาบุ๊กมาร์ก

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

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


20

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

SELECT
    [ID],
    [DeviceID],
    [IsPUp],
    [IsWebUp],
    [IsPingUp],
    [DateEntered]
FROM [dbo].[Heartbeats]
WHERE
    [ID] IN
(
    -- Keys
    SELECT TOP (1000)
        [ID]
    FROM [dbo].[Heartbeats]
    WHERE 
        [DateEntered] >= CONVERT(datetime, '2011-08-30', 121)
        AND [DateEntered]  < CONVERT(datetime, '2011-08-31', 121)
);

แผนแบบสอบถาม

เปรียบเทียบแผนนั้นกับแผนที่สร้างขึ้นเมื่อดัชนีที่ไม่ใช่คลัสเตอร์ถูกบังคับด้วยคำใบ้:

SELECT TOP (1000) 
    * 
FROM [dbo].[Heartbeats] WITH (INDEX(CommonQueryIndex))
WHERE 
    [DateEntered] BETWEEN '2011-08-30' and '2011-08-31';

ดัชนีเคล็ดลับแผนบังคับ

โดยพื้นฐานแล้วแผนจะเหมือนกัน (การค้นหาคีย์ไม่มีอะไรมากไปกว่าการค้นหาในดัชนีคลัสเตอร์) รูปแบบแผนทั้งสองจะทำการค้นหาเพียงครั้งเดียวบนดัชนีที่ไม่ทำคลัสเตอร์และมีการค้นหาสูงสุด 1,000 รายการในดัชนีคลัสเตอร์

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

ค่าใช้จ่ายในการสแกนและแสวงหา

ในระดับที่สูงมากรูปแบบค่าใช้จ่ายของเครื่องมือเพิ่มประสิทธิภาพสำหรับการสแกนและการค้นหานั้นค่อนข้างง่าย: มันประมาณว่าการค้นหาแบบสุ่ม 320 ครั้งมีค่าใช้จ่ายเท่ากันกับการอ่าน 1,350 หน้าในการสแกน สิ่งนี้อาจมีความคล้ายคลึงกับความสามารถของฮาร์ดแวร์ของระบบ I / O ที่ทันสมัย ​​แต่ก็ทำงานได้ดีพอ ๆ กับแบบจำลองที่ใช้งานได้จริง

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

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

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

เป้าหมายแถว

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

รูปภาพที่ปรากฏในคำตอบนี้ถูกสร้างขึ้นโดยใช้SQL ยามแผน Explorer ที่

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