ฉันกำลังพยายามสร้างแผนการสืบค้นตัวอย่างเพื่อแสดงว่าทำไมชุดผลลัพธ์สองชุดของยูเนี่ยนจึงดีกว่าการใช้ OR ในประโยค JOIN แผนแบบสอบถามที่ฉันเขียนทำให้ฉันนิ่งงัน ฉันใช้ฐานข้อมูล StackOverflow กับดัชนีที่ไม่ได้เป็นคลัสเตอร์ใน Users.Reputation
CREATE NONCLUSTERED INDEX IX_NC_REPUTATION ON dbo.USERS(Reputation)
SELECT DISTINCT Users.Id
FROM dbo.Users
INNER JOIN dbo.Posts
ON Users.Id = Posts.OwnerUserId
OR Users.Id = Posts.LastEditorUserId
WHERE Users.Reputation = 5
แผนการสืบค้นอยู่ที่https://www.brentozar.com/pastetheplan/?id=BkpZU1MZEระยะเวลาการสืบค้นสำหรับฉันคือ 4:37 นาทีส่งคืนแถว 26612
ฉันไม่เคยเห็นรูปแบบการสแกนคงที่นี้ถูกสร้างขึ้นจากตารางที่มีอยู่ก่อนหน้านี้ - ฉันไม่คุ้นเคยกับสาเหตุที่มีการสแกนค่าคงที่สำหรับทุก ๆ แถวเมื่อการสแกนแบบคงที่มักใช้กับแถวเดียวที่ป้อนโดยผู้ใช้ เช่น SELECT GETDATE () ทำไมถึงใช้ที่นี่? ฉันขอขอบคุณคำแนะนำในการอ่านแผนแบบสอบถามนี้
ถ้าฉันแยก OR ออกเป็น UNION มันจะสร้างแผนมาตรฐานที่ใช้ใน 12 วินาทีโดยมี 26612 แถวเดียวกันกลับมา
SELECT Users.Id
FROM dbo.Users
INNER JOIN dbo.Posts
ON Users.Id = Posts.OwnerUserId
WHERE Users.Reputation = 5
UNION
SELECT Users.Id
FROM dbo.Users
INNER JOIN dbo.Posts
ON Users.Id = Posts.LastEditorUserId
WHERE Users.Reputation = 5
ฉันตีความแผนนี้เมื่อทำสิ่งนี้:
- รับแถวทั้งหมด 41782500 จากโพสต์ (จำนวนแถวจริงตรงกับการสแกน CI บนโพสต์)
- สำหรับแต่ละ 41782500 แถวในกระทู้:
- ผลิตสเกลาร์:
- Expr1005: OwnerUserId
- Expr1006: OwnerUserId
- Expr1004: ค่าคงที่ 62
- Expr1008: LastEditorUserId
- Expr1009: LastEditorUserId
- Expr1007: ค่าคงที่ 62
- ในการเรียงต่อกัน:
- Exp1010: ถ้า Expr1005 (OwnerUserId) ไม่เป็นโมฆะให้ใช้อย่างอื่นใช้ Expr1008 (LastEditorUserID)
- Expr1011: ถ้า Expr1006 (OwnerUserId) ไม่เป็นโมฆะให้ใช้งานนั้นมิฉะนั้นให้ใช้ Expr1009 (LastEditorUserId)
- Expr1012: ถ้า Expr1004 (62) เป็นโมฆะให้ใช้มิเช่นนั้นให้ใช้ Expr1007 (62)
- ในสเกลาร์คำนวณ: ฉันไม่รู้ว่าแอมเปอร์แซนด์ทำอะไร
- Expr1013: 4 [และ?] 62 (Expr1012) = 4 และ OwnerUserId IS NULL (NULL = Expr1010)
- Expr1014: 4 [และ?] 62 (Expr1012)
- Expr1015: 16 และ 62 (Expr1012)
- เรียงตาม:
- Expr1013 ลำดับ
- Expr1014 Asc
- Expr1010 Asc
- Expr1015 ลำดับ
- ใน Merge Interval จะลบ Expr1013 และ Expr1015 (นี่คืออินพุต แต่ไม่ใช่เอาต์พุต)
- ในการค้นหาดัชนีด้านล่างการวนซ้ำซ้อนกันการใช้ Expr1010 และ Expr1011 เป็นการค้นหาเพรดิเคต แต่ฉันไม่เข้าใจว่าจะเข้าถึงสิ่งเหล่านี้ได้อย่างไรเมื่อยังไม่ได้เข้าร่วมลูปซ้อนจาก IX_NC_REPUTATION กับทรีย่อยที่มี Expr1010 และ Expr1011 .
- การเข้าร่วมลูปซ้อนจะส่งคืนเฉพาะ Users.ID ที่มีการจับคู่ในทรีย่อยก่อนหน้านี้ เนื่องจากการเลื่อนลงภาคแสดงผลแถวทั้งหมดที่ส่งคืนจากดัชนีค้นหาบน IX_NC_REPUTATION จะถูกส่งกลับ
- การวนซ้ำซ้อนกันครั้งสุดท้ายเข้าร่วม: สำหรับแต่ละเรคคอร์ดการโพสต์เอาท์พุท Users.Id ที่พบการแข่งขันในชุดข้อมูลด้านล่าง
SELECT Users.Id FROM dbo.Users WHERE Users.Reputation = 5 AND EXISTS (SELECT 1 FROM dbo.Posts WHERE Users.Id IN (Posts.OwnerUserId, Posts.LastEditorUserId) ) ;
SELECT Users.Id FROM dbo.Users WHERE Users.Reputation = 5 AND ( EXISTS (SELECT 1 FROM dbo.Posts WHERE Users.Id = Posts.OwnerUserId) OR EXISTS (SELECT 1 FROM dbo.Posts WHERE Users.Id = Posts.LastEditorUserId) ) ;