SQL Server กำหนดลำดับของคอลัมน์คีย์อย่างไรในคำขอดัชนีที่ขาดหายไป


คำตอบ:


44

เมื่อ SQL Server สร้างคำแนะนำดัชนีที่ขาดหายไปสำหรับแผนแบบสอบถามเฉพาะจะแยกคอลัมน์คีย์ที่เป็นไปได้ออกเป็น 2 กลุ่ม ชุดแรกประกอบด้วยคอลัมน์ที่แนะนำทั้งหมดที่เป็นส่วนหนึ่งของเพรดิเคตความเท่าเทียม ชุดที่สองประกอบด้วยคอลัมน์ที่แนะนำทั้งหมดซึ่งเป็นส่วนหนึ่งของเพรดิเคต INEQUALITY

ภายในแต่ละชุดคอลัมน์จะเรียงลำดับตามตำแหน่งลำดับของคอลัมน์ตามคำจำกัดความของตาราง

(ขอบคุณมากที่ Brent Ozar สำหรับการสร้างสคริปต์ซ้ำกับฐานข้อมูล Stack Overflow เพื่อพิสูจน์สิ่งนี้!)

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

CREATE TABLE dbo.NumberLetterDate (ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, 
fINT INT, fNVARCHAR NVARCHAR(40), fDATE DATETIME, AboutMe NVARCHAR(MAX));
GO
CREATE TABLE dbo.LetterDateNumber (ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, 
fNVARCHAR NVARCHAR(40), fDATE DATETIME, fINT INT, AboutMe NVARCHAR(MAX));
GO
CREATE TABLE dbo.DateNumberLetter (ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
fDATE DATETIME, fINT INT, fNVARCHAR NVARCHAR(40), AboutMe NVARCHAR(MAX));
GO

2. เติมตารางด้วยข้อมูลเดียวกัน รับ 100,000 แถวจากตารางผู้ใช้พร้อมการกระจายข้อมูลจริง

INSERT INTO dbo.NumberLetterDate(fINT, fNVARCHAR, fDATE, AboutMe)
SELECT TOP 100000 Age, DisplayName, LastAccessDate, AboutMe
  FROM dbo.Users WITH (NOLOCK)
  ORDER BY Id;
GO
INSERT INTO dbo.LetterDateNumber(fINT, fNVARCHAR, fDATE, AboutMe)
SELECT TOP 100000 Age, DisplayName, LastAccessDate, AboutMe
  FROM dbo.Users WITH (NOLOCK)
  ORDER BY Id;
GO
INSERT INTO dbo.DateNumberLetter(fINT, fNVARCHAR, fDATE, AboutMe)
SELECT TOP 100000 Age, DisplayName, LastAccessDate, AboutMe
  FROM dbo.Users WITH (NOLOCK)
  ORDER BY Id;
GO

3. เขียนแบบสอบถามที่ต้องการดัชนี เริ่มต้นด้วยตัวกรองความเท่าเทียมกัน 3 ตัวกรองค่าที่แน่นอนในฟิลด์ทั้ง 3 โปรดทราบว่าข้อความค้นหาทั้ง 3 รายการมีเขตข้อมูลเดียวกันในลำดับเดียวกัน:

SELECT ID
  FROM dbo.NumberLetterDate
  WHERE fINT = 100
  AND fNVARCHAR = 'Brent Ozar'
  AND fDATE = '2018/01/01'
  AND 1 = (SELECT 1);

SELECT ID
  FROM dbo.LetterDateNumber
  WHERE fINT = 100
  AND fNVARCHAR = 'Brent Ozar'
  AND fDATE = '2018/01/01'
  AND 1 = (SELECT 1);

SELECT ID
  FROM dbo.DateNumberLetter
  WHERE fINT = 100
  AND fNVARCHAR = 'Brent Ozar'
  AND fDATE = '2018/01/01'
  AND 1 = (SELECT 1);
GO

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

แผนการดำเนินการที่มี 3 ฟิลด์ความเท่าเทียมกัน

ในแผนการดำเนินการลำดับของคอลัมน์ในคำขอดัชนีที่ขาดหายไปนั้นตรงกับลำดับคอลัมน์ในตาราง ตัวอย่างเช่นใน dbo.NumberLetterDate คอลัมน์ตัวเลขเป็นอันดับแรกดังนั้นจึงเป็นครั้งแรกในคำขอดัชนีที่ขาดหายไปเช่นกัน:

  • บน dbo.NumberLetterDate ดัชนีที่หายไปจะอยู่ใน fINT (ตัวเลข), fLetter (nvarchar), fDate, ลำดับเดียวกันของเขตข้อมูลในตาราง
  • บน dbo.LetterDateNumber ลำดับดัชนีจะเปลี่ยนเป็น fNVARCHAR, fDATE, fINT
  • บน dbo.DateNumberLetter ลำดับดัชนีจะเปลี่ยนเป็น fDATE, fINT, fNVARCHAR

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

4. ผสมในตัวกรองอสมการ บนฟิลด์ INT เช่นใส่ <> 100 เป็นตัวกรอง:

SELECT ID
  FROM dbo.NumberLetterDate
  WHERE fINT <> 100
  AND fNVARCHAR = 'Brent Ozar'
  AND fDATE = '2018/01/01'
  AND 1 = (SELECT 1);

SELECT ID
  FROM dbo.LetterDateNumber
  WHERE fINT <> 100
  AND fNVARCHAR = 'Brent Ozar'
  AND fDATE = '2018/01/01'
  AND 1 = (SELECT 1);

SELECT ID
  FROM dbo.DateNumberLetter
  WHERE fINT <> 100
  AND fNVARCHAR = 'Brent Ozar'
  AND fDATE = '2018/01/01'
  AND 1 = (SELECT 1);
GO

ในแผนการดำเนินการเขตความเสมอภาคไปก่อนจากนั้นเขตความไม่เท่าเทียมกันดังนั้นที่นี่ FINT จะปรากฏขึ้นล่าสุดในคำขอดัชนีที่หายไปทั้ง 3 รายการเนื่องจากเป็นการค้นหาความไม่เท่าเทียมกัน:

แผนการดำเนินการที่มีความเท่าเทียมกัน 2 รายการและการค้นหาความไม่เท่าเทียมกัน 1 ครั้ง

5. ใช้ฟิลเตอร์อสมการ 3 ตัว ใช้การค้นหาเดียวกันสำหรับทุกสาขา (<>):

SELECT ID
  FROM dbo.NumberLetterDate
  WHERE fINT <> 100
  AND fNVARCHAR <> 'Brent Ozar'
  AND fDATE <> '2018/01/01'
  AND 1 = (SELECT 1);

SELECT ID
  FROM dbo.LetterDateNumber
  WHERE fINT <> 100
  AND fNVARCHAR <> 'Brent Ozar'
  AND fDATE <> '2018/01/01'
  AND 1 = (SELECT 1);

SELECT ID
  FROM dbo.DateNumberLetter
  WHERE fINT <> 100
  AND fNVARCHAR <> 'Brent Ozar'
  AND fDATE <> '2018/01/01'
  AND 1 = (SELECT 1);
GO

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

แผนการดำเนินการที่มีการค้นหาอสมการ 3 ครั้ง

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