ฉันมีคอลัมน์ที่คำนวณแล้วยังคงอยู่บนโต๊ะซึ่งเป็นเพียงคอลัมน์ที่ต่อกันเช่น
CREATE TABLE dbo.T
(
ID INT IDENTITY(1, 1) NOT NULL CONSTRAINT PK_T_ID PRIMARY KEY,
A VARCHAR(20) NOT NULL,
B VARCHAR(20) NOT NULL,
C VARCHAR(20) NOT NULL,
D DATE NULL,
E VARCHAR(20) NULL,
Comp AS A + '-' + B + '-' + C PERSISTED NOT NULL
);
ในสิ่งนี้Comp
ไม่ซ้ำกันและ D เป็นค่าที่ถูกต้องตั้งแต่วันที่ของการรวมกันของแต่ละครั้งA, B, C
ดังนั้นฉันใช้แบบสอบถามต่อไปนี้เพื่อรับวันที่สิ้นสุดสำหรับแต่ละวันA, B, C
(โดยพื้นฐานแล้วคือวันที่เริ่มต้นถัดไปสำหรับค่า Comp เดียวกัน):
SELECT t1.ID,
t1.Comp,
t1.D,
D2 = ( SELECT TOP 1 t2.D
FROM dbo.T t2
WHERE t2.Comp = t1.Comp
AND t2.D > t1.D
ORDER BY t2.D
)
FROM dbo.T t1
WHERE t1.D IS NOT NULL -- DON'T CARE ABOUT INACTIVE RECORDS
ORDER BY t1.Comp;
ฉันเพิ่มดัชนีไปยังคอลัมน์ที่คำนวณแล้วเพื่อช่วยในแบบสอบถามนี้ (และอื่น ๆ ):
CREATE NONCLUSTERED INDEX IX_T_Comp_D ON dbo.T (Comp, D) WHERE D IS NOT NULL;
แผนแบบสอบถามทำให้ฉันประหลาดใจ ฉันคิดว่าเนื่องจากฉันมีส่วนคำสั่งระบุD IS NOT NULL
และฉันกำลังเรียงลำดับComp
และไม่อ้างอิงคอลัมน์ใด ๆ นอกดัชนีที่ดัชนีในคอลัมน์คำนวณสามารถใช้สแกน t1 และ t2 แต่ฉันเห็นดัชนีคลัสเตอร์ การสแกน
ดังนั้นฉันจึงบังคับให้ใช้ดัชนีนี้เพื่อดูว่ามันให้ผลที่ดีกว่า:
SELECT t1.ID,
t1.Comp,
t1.D,
D2 = ( SELECT TOP 1 t2.D
FROM dbo.T t2
WHERE t2.Comp = t1.Comp
AND t2.D > t1.D
ORDER BY t2.D
)
FROM dbo.T t1 WITH (INDEX (IX_T_Comp_D))
WHERE t1.D IS NOT NULL
ORDER BY t1.Comp;
ซึ่งให้แผนนี้
สิ่งนี้แสดงว่ามีการใช้การค้นหาคีย์โดยมีรายละเอียดดังนี้:
ตอนนี้ตามเอกสารของ SQL-Server:
คุณสามารถสร้างดัชนีในคอลัมน์จากการคำนวณที่กำหนดด้วยค่าที่กำหนดได้ แต่ไม่ชัดเจนนิพจน์หากคอลัมน์ถูกทำเครื่องหมาย PERSISTED ในคำสั่ง CREATE TABLE หรือ ALTER TABLE ซึ่งหมายความว่า Database Engine เก็บค่าที่คำนวณในตารางและอัพเดตเมื่อคอลัมน์อื่น ๆ ที่ขึ้นกับคอลัมน์ที่คำนวณนั้นถูกอัพเดต โปรแกรมฐานข้อมูลใช้ค่าที่เก็บไว้เหล่านี้เมื่อสร้างดัชนีในคอลัมน์และเมื่อมีการอ้างอิงดัชนีในแบบสอบถาม ตัวเลือกนี้ช่วยให้คุณสามารถสร้างดัชนีในคอลัมน์ที่คำนวณได้เมื่อโปรแกรมฐานข้อมูลไม่สามารถพิสูจน์ได้อย่างแม่นยำว่าฟังก์ชันที่ส่งคืนนิพจน์คอลัมน์ที่คำนวณแล้วโดยเฉพาะอย่างยิ่งฟังก์ชัน CLR ที่สร้างขึ้นใน. NET Framework นั้นเป็นทั้งกำหนดและแม่นยำ
ดังนั้นถ้าอย่างที่เอกสารบอกว่า"โปรแกรมฐานข้อมูลจัดเก็บค่าที่คำนวณในตาราง"และค่ายังถูกเก็บไว้ในดัชนีของฉันทำไมการค้นหาคีย์จึงต้องได้รับ A, B และ C เมื่อไม่ได้อ้างอิง แบบสอบถามทั้งหมดหรือไม่ ฉันคิดว่ามันถูกใช้เพื่อคำนวณคอมพ์ แต่ทำไม นอกจากนี้ทำไมแบบสอบถามสามารถใช้ดัชนีในt2
แต่ไม่ได้อยู่t1
?
แบบสอบถามและ DDL บน SQL Fiddle
NB ฉันติดแท็ก SQL Server 2008 เพราะนี่เป็นเวอร์ชันที่ปัญหาหลักของฉันเปิดอยู่ แต่ฉันก็มีพฤติกรรมเหมือนกันในปี 2555