เหตุใดแบบสอบถามนี้จึงไม่ใช้สปูลดัชนี


23

ฉันกำลังถามคำถามนี้เพื่อให้เข้าใจถึงพฤติกรรมของเครื่องมือเพิ่มประสิทธิภาพและเข้าใจขีด จำกัด รอบ ๆ ดัชนีสิ่งของ สมมติว่าฉันใส่จำนวนเต็มจาก 1 ถึง 10,000 ลงในกอง:

CREATE TABLE X_10000 (ID INT NOT NULL);
truncate table X_10000;

INSERT INTO X_10000 WITH (TABLOCK)
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

และบังคับให้วงวนซ้อนกันเข้าร่วมกับMAXDOP 1:

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID = b.ID
OPTION (LOOP JOIN, MAXDOP 1);

นี่เป็นการกระทำที่ไม่เป็นมิตรที่จะใช้กับ SQL Server การรวมลูปซ้อนกันมักจะไม่เป็นตัวเลือกที่ดีเมื่อทั้งสองตารางไม่มีดัชนีที่เกี่ยวข้อง นี่คือแผน:

ข้อความค้นหาไม่ดี

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

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

SELECT *
FROM X_10000 a
CROSS APPLY (SELECT TOP (9223372036854775807) b.ID FROM X_10000 b WHERE a.ID = b.ID) ca
OPTION (LOOP JOIN, MAXDOP 1);

วิธีแก้ปัญหา 1

แบบสอบถามนี้ยังมีสปูลดัชนีและเสร็จสิ้นในเวลาน้อยกว่าหนึ่งวินาที:

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID >= b.ID AND a.ID <= b.ID
OPTION (LOOP JOIN, MAXDOP 1);

วิธีแก้ปัญหา 2

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

คำตอบ:


20

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

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

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

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

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

SELECT * 
FROM dbo.X_1000 AS a
CROSS APPLY (SELECT * FROM dbo.X_1000 AS b WHERE b.ID = a.ID) AS b
OPTION (QUERYTRACEON 9114);

สปูลแผน

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

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