@Id
ฉันจะคิดว่าคุณมีข้อมูลเบ้ที่คุณไม่ต้องการที่จะใช้คำแนะนำแบบสอบถามที่จะบังคับให้เพิ่มประสิทธิภาพสิ่งที่ต้องทำและที่คุณต้องการที่จะได้รับผลงานที่ดีสำหรับค่าเข้าทั้งหมดเป็นไปได้ของ คุณสามารถรับแผนแบบสอบถามเพื่อรับประกันว่าจะต้องอ่านตรรกะเพียงไม่กี่หยิบสำหรับค่าอินพุตใด ๆ ที่เป็นไปได้หากคุณต้องการสร้างดัชนีคู่ต่อไปนี้ (หรือเทียบเท่า):
CREATE INDEX GetMinSomeTimestamp ON dbo.MyTable (Id, SomeTimestamp) WHERE SomeBit = 1;
CREATE INDEX GetMaxSomeInt ON dbo.MyTable (Id, SomeInt) WHERE SomeBit = 1;
ด้านล่างคือข้อมูลการทดสอบของฉัน ฉันวางแถว 13 M ลงในตารางและทำให้ครึ่งหนึ่งของพวกเขามีค่า'3A35EA17-CE7E-4637-8319-4C517B6E48CA'
สำหรับId
คอลัมน์
DROP TABLE IF EXISTS dbo.MyTable;
CREATE TABLE dbo.MyTable (
Id uniqueidentifier,
SomeTimestamp DATETIME2,
SomeInt INT,
SomeBit BIT,
FILLER VARCHAR(100)
);
INSERT INTO dbo.MyTable WITH (TABLOCK)
SELECT NEWID(), CURRENT_TIMESTAMP, 0, 1, REPLICATE('Z', 100)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
INSERT INTO dbo.MyTable WITH (TABLOCK)
SELECT '3A35EA17-CE7E-4637-8319-4C517B6E48CA', CURRENT_TIMESTAMP, 0, 1, REPLICATE('Z', 100)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
คำค้นหานี้อาจดูแปลก ๆ เล็กน้อยในตอนแรก:
DECLARE @Id UNIQUEIDENTIFIER = '3A35EA17-CE7E-4637-8319-4C517B6E48CA'
SELECT
@Id,
st.SomeTimestamp,
si.SomeInt
FROM (
SELECT TOP (1) SomeInt, Id
FROM dbo.MyTable
WHERE Id = @Id
AND SomeBit = 1
ORDER BY SomeInt DESC
) si
CROSS JOIN (
SELECT TOP (1) SomeTimestamp, Id
FROM dbo.MyTable
WHERE Id = @Id
AND SomeBit = 1
ORDER BY SomeTimestamp ASC
) st;
มันถูกออกแบบมาเพื่อใช้ประโยชน์จากการจัดลำดับของดัชนีเพื่อค้นหาค่า min หรือ max ด้วยการอ่านเชิงตรรกะ CROSS JOIN
มีเพื่อให้ได้ผลลัพธ์ที่ถูกต้องเมื่อมีไม่ตรงกับแถวใด ๆ สำหรับ@Id
ค่า แม้ว่าฉันจะกรองค่าที่ได้รับความนิยมมากที่สุดในตาราง (การจับคู่ 6.5 ล้านแถว) ฉันได้รับการอ่านเชิงตรรกะ 8 ครั้งเท่านั้น:
ตาราง 'MyTable' สแกนจำนวน 2, ตรรกะอ่าน 8
นี่คือแผนแบบสอบถาม:
ดัชนีทั้งสองหา 0 หรือ 1 แถว มันมีประสิทธิภาพมาก แต่การสร้างดัชนีสองรายการอาจเกินความจำเป็นสำหรับสถานการณ์ของคุณ คุณสามารถพิจารณาดัชนีต่อไปนี้แทน:
CREATE INDEX CoveringIndex ON dbo.MyTable (Id) INCLUDE (SomeTimestamp, SomeInt) WHERE SomeBit = 1;
ตอนนี้แผนคิวรีสำหรับเคียวรีดั้งเดิม (พร้อมด้วยMAXDOP 1
คำใบ้เพิ่มเติม) จะดูแตกต่างออกไปเล็กน้อย:
การค้นหาคีย์ไม่จำเป็นอีกต่อไป ด้วยเส้นทางการเข้าถึงที่ดีกว่าที่ควรใช้งานได้ดีกับอินพุตทั้งหมดคุณไม่ควรกังวลเกี่ยวกับเครื่องมือเพิ่มประสิทธิภาพในการเลือกแผนแบบสอบถามที่ไม่ถูกต้องเนื่องจากเวกเตอร์ความหนาแน่น อย่างไรก็ตามการค้นหาและดัชนีนี้จะไม่ได้มีประสิทธิภาพเท่ากับอีกแบบสอบถามหากคุณค้นหา@Id
มูลค่าที่เป็นที่นิยม
ตาราง 'MyTable' จำนวนการสแกน 1, ตรรกะอ่าน 33757