ส่วนหนึ่งของแบบสอบถามเริ่มต้นของคุณมีดังนี้
FROM [dbo].[calendar] a
LEFT JOIN [dbo].[colleagueList] b
ON b.[Date] = a.d
WHERE DAY(a.[d]) = 1
AND a.[d] BETWEEN @dateStart AND COALESCE(@dateEnd,@dateStart)
ส่วนของแผนนั้นแสดงไว้ด้านล่าง
ข้อความค้นหาที่แก้ไขของคุณ BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)
มีไว้สำหรับการเข้าร่วมเดียวกัน
ความแตกต่างนั้นเป็นสิ่งที่ISNULL
ทำให้ง่ายขึ้นอีกและด้วยเหตุนี้คุณจึงได้สถิติเชิงสถิติที่แม่นยำยิ่งขึ้นในการเข้าร่วมครั้งต่อไป นี่คือฟังก์ชันที่มีค่าในตารางแบบอินไลน์และคุณกำลังเรียกมันด้วยค่าที่แท้จริงเพื่อให้สามารถทำสิ่งที่ต้องการ
a.[d] BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)
a.[d] BETWEEN '2013-06-01' AND ISNULL(NULL,'2013-06-01')
a.[d] BETWEEN '2013-06-01' AND '2013-06-01'
a.[d] = '2013-06-01'
และในขณะที่มีการเข้าร่วม equi สรุปแผนนอกจากนี้ยังแสดงให้เห็นถึงความเท่าเทียมกันกริยาb.[Date] = a.d
b.[Date] = '2013-06-01'
ผลที่ตามมาคือการประมาณความ28,393
น่าจะเป็นของแถวที่ค่อนข้างแม่นยำ
สำหรับCASE
/ COALESCE
รุ่นเมื่อใด@dateStart
และ@dateEnd
มีค่าเท่ากันมันจะทำให้ตกลงไปยังนิพจน์ความเสมอภาคเดียวกันได้ง่ายขึ้นและให้แผนเดียวกัน แต่เมื่อใด@dateStart = '2013-06-01'
และ@dateEnd IS NULL
มันไปเท่าที่
a.[d]>='2013-06-01' AND a.[Date]<=CASE WHEN (1) THEN '2013-06-01' ELSE NULL END
ColleagueList
ที่มันยังใช้เป็นคำกริยาโดยนัย จำนวนแถวโดยประมาณในครั้งนี้คือ79.8
แถว
เข้าร่วมต่อไปคือ
LEFT JOIN colleagueTime
ON colleagueTime.TC_DATE = colleagueList.Date
AND colleagueTime.ASSOC_ID = CAST(colleagueList.ID AS VARCHAR(10))
colleagueTime
เป็น3,249,590
ตารางแถวที่เห็นได้ชัดคือฮีปที่ไม่มีดัชนีที่มีประโยชน์
ความคลาดเคลื่อนในการประมาณนี้ส่งผลต่อตัวเลือกการเข้าร่วมที่ใช้ ISNULL
แผนเลือกกัญชาเข้าร่วมว่าเพียงแค่สแกนตารางครั้ง COALESCE
แผนเลือกลูปซ้อนกันเข้าร่วมและประมาณการว่ามันจะยังคงเป็นเพียงต้องสแกนตารางครั้งและสามารถที่จะ spool ผลและเล่นมัน 78 ครั้ง นั่นคือมันประมาณว่าพารามิเตอร์ที่สัมพันธ์กันจะไม่เปลี่ยนแปลง
จากความจริงที่ว่าแผนการลูปซ้อนกันยังคงดำเนินต่อไปหลังจากสองชั่วโมงข้อสันนิษฐานของการสแกนครั้งเดียวต่อcolleagueTime
ดูเหมือนว่าจะไม่ถูกต้องสูง
สำหรับสาเหตุที่จำนวนแถวโดยประมาณระหว่างการรวมสองครั้งนั้นต่ำกว่านี้มากฉันไม่แน่ใจโดยที่ไม่สามารถดูสถิติในตารางได้ วิธีเดียวที่ฉันสามารถจัดการกับการนับแถวโดยประมาณที่มากในการทดสอบของฉันคือการเพิ่มจำนวนNULL
แถว (นี่เป็นการลดจำนวนแถวโดยประมาณแม้ว่าจำนวนแถวที่แท้จริงจะกลับมาเหมือนเดิม)
จำนวนแถวโดยประมาณในCOALESCE
แผนข้อมูลการทดสอบของฉันอยู่ในลำดับ
number of rows matching >= condition * 30% * (proportion of rows in the table not null)
หรือใน SQL
SELECT 1E0 * COUNT([Date]) / COUNT(*) * ( COUNT(CASE
WHEN [Date] >= '2013-06-01' THEN 1
END) * 0.30 )
FROM [dbo].[colleagueList]
แต่นี่ไม่ได้เป็นรูปสี่เหลี่ยมจัตุรัสกับความคิดเห็นของคุณว่าคอลัมน์ไม่มีNULL
ค่า