Bagian dari permintaan awal Anda adalah sebagai berikut.
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)
Bagian rencana itu ditunjukkan di bawah ini

Permintaan Anda yang direvisi BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)memiliki ini untuk gabungan yang sama

Perbedaannya tampaknya yang ISNULLmenyederhanakan lebih lanjut dan sebagai hasilnya Anda mendapatkan statistik kardinalitas yang lebih akurat masuk ke gabung berikutnya. Ini adalah fungsi bernilai tabel inline dan Anda memanggilnya dengan nilai literal sehingga dapat melakukan sesuatu seperti.
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'
Dan karena ada equi join predikat b.[Date] = a.d, rencana itu juga menunjukkan predikat kesetaraan b.[Date] = '2013-06-01'. Akibatnya, perkiraan kardinalitas dari 28,393baris cenderung cukup akurat.
Untuk versi CASE/ COALESCEkapan @dateStartdan @dateEndmemiliki nilai yang sama maka itu menyederhanakan OK untuk persamaan kesetaraan yang sama dan memberikan rencana yang sama tetapi kapan @dateStart = '2013-06-01'dan @dateEnd IS NULLhanya berjalan sejauh
a.[d]>='2013-06-01' AND a.[Date]<=CASE WHEN (1) THEN '2013-06-01' ELSE NULL END
yang juga berlaku sebagai predikat tersirat pada ColleagueList. Perkiraan jumlah baris kali ini adalah 79.8baris.
Bergabung berikutnya adalah
LEFT JOIN colleagueTime
ON colleagueTime.TC_DATE = colleagueList.Date
AND colleagueTime.ASSOC_ID = CAST(colleagueList.ID AS VARCHAR(10))
colleagueTimeadalah 3,249,590tabel baris yang (sekali lagi) ternyata tumpukan tanpa indeks yang berguna.
Perbedaan dalam estimasi ini memengaruhi pilihan bergabung yang digunakan. The ISNULLrencana memilih hash join yang hanya memindai meja sekali. The COALESCErencana memilih sebuah loop bersarang bergabung dan perkiraan bahwa itu akan tetap hanya perlu memindai meja sekali dan dapat spool hasil dan memutar ulang 78 kali. yaitu memperkirakan bahwa parameter berkorelasi tidak akan berubah.
Dari kenyataan bahwa rencana loop bersarang masih berjalan setelah dua jam, asumsi pemindaian tunggal terhadap ini colleagueTimetampaknya sangat tidak akurat.
Adapun mengapa perkiraan jumlah baris antara dua gabungan jauh lebih rendah, saya tidak yakin tanpa bisa melihat statistik di tabel. Satu-satunya cara saya berhasil memiringkan jumlah baris yang diperkirakan dalam pengujian saya adalah menambahkan banyak NULLbaris (ini mengurangi jumlah baris yang diperkirakan meskipun jumlah sebenarnya baris yang dikembalikan tetap sama).
Perkiraan jumlah baris dalam COALESCEpaket dengan data pengujian saya adalah dalam urutan
number of rows matching >= condition * 30% * (proportion of rows in the table not null)
Atau dalam SQL
SELECT 1E0 * COUNT([Date]) / COUNT(*) * ( COUNT(CASE
WHEN [Date] >= '2013-06-01' THEN 1
END) * 0.30 )
FROM [dbo].[colleagueList]
tetapi ini tidak sesuai dengan komentar Anda bahwa kolom tidak memiliki NULLnilai.