Saya membuat fungsi yang menerima tanggal mulai dan berakhir, dengan tanggal akhir menjadi opsional. Saya kemudian menulis CASE
di filter untuk menggunakan tanggal mulai jika tidak ada tanggal akhir yang dilewati.
CASE WHEN @dateEnd IS NULL
THEN @dateStart
ELSE @dateEnd
END
Ketika saya memanggil fungsi untuk bulan terakhir dari data:
SELECT * FROM theFunction ('2013-06-01', NULL)
... permintaannya hang. Jika saya menentukan tanggal akhir:
SELECT * FROM theFunction ('2013-06-01', '2013-06-01')
... hasilnya dikembalikan secara normal. Saya mengambil kode dari fungsi dan menjalankannya dengan baik di dalam jendela permintaan. Saya tidak bisa menduplikasi masalah biola juga. Kueri seperti:
SELECT * FROM theFunction ('2013-04-01', '2013-06-01')
... juga berfungsi dengan baik.
Apakah ada sesuatu dalam kueri (di bawah) yang dapat menyebabkan fungsi hang ketika a NULL
disahkan untuk tanggal akhir?
- Rencana eksekusi untuk
SELECT * FROM theFunction ('2013-06-01', '2013-06-01')
- Perkiraan rencana untuk
SELECT * FROM theFunction ('2013-06-01', NULL)
sql-server
sql-server-2008-r2
Kermit
sumber
sumber
CASE
denganCOALESCE(@dateEnd,@dateStart)
, apakah masalah masih muncul?ISNULL()
?SELECT task_state FROM sys.dm_os_tasks WHERE session_id = x
ditampilkan? Jika menghabiskan banyak waktu tidak diRUNNING
negara apa jenis menunggu sesi yang masuksys.dm_os_waiting_tasks
?COALESCE
.ISNULL
memperbaikinya.Jawaban:
Bagian dari permintaan awal Anda adalah sebagai berikut.
Bagian rencana itu ditunjukkan di bawah ini
Permintaan Anda yang direvisi
BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)
memiliki ini untuk gabungan yang samaPerbedaannya tampaknya yang
ISNULL
menyederhanakan 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.Dan karena ada equi join predikat
b.[Date] = a.d
, rencana itu juga menunjukkan predikat kesetaraanb.[Date] = '2013-06-01'
. Akibatnya, perkiraan kardinalitas dari28,393
baris cenderung cukup akurat.Untuk versi
CASE
/COALESCE
kapan@dateStart
dan@dateEnd
memiliki 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 NULL
hanya berjalan sejauhyang juga berlaku sebagai predikat tersirat pada
ColleagueList
. Perkiraan jumlah baris kali ini adalah79.8
baris.Bergabung berikutnya adalah
colleagueTime
adalah3,249,590
tabel baris yang (sekali lagi) ternyata tumpukan tanpa indeks yang berguna.Perbedaan dalam estimasi ini memengaruhi pilihan bergabung yang digunakan. The
ISNULL
rencana memilih hash join yang hanya memindai meja sekali. TheCOALESCE
rencana 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
colleagueTime
tampaknya 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
NULL
baris (ini mengurangi jumlah baris yang diperkirakan meskipun jumlah sebenarnya baris yang dikembalikan tetap sama).Perkiraan jumlah baris dalam
COALESCE
paket dengan data pengujian saya adalah dalam urutanAtau dalam SQL
tetapi ini tidak sesuai dengan komentar Anda bahwa kolom tidak memiliki
NULL
nilai.sumber
NULL
nilai untuk tanggal di tabel mana pun.dbo
tidak terdaftar. Hanya skema lain yang tidak saya gunakan.Sepertinya ada masalah dengan tipe data.
ISNULL
memperbaiki masalah (terima kasih ypercube ). Setelah beberapa penelitian,COALESCE
adalah setara denganCASE
pernyataan yang saya gunakan:Paul White menjelaskan bahwa:
Untuk menghindari masalah tipe data apa pun, tampaknya
ISNULL
ini adalah fungsi yang tepat untuk digunakan untuk menangani hanya dua ekspresi.Kutipan Rencana XML
Menggunakan rencana XML
CASE
, ekspresi 2 adalahNULL
:Menggunakan rencana XML
CASE
, ekspresi 2 adalah tanggal:Menggunakan rencana XML
ISNULL
, ekspresi 2 adalahNULL
:Menggunakan rencana XML
ISNULL
, ekspresi 2 adalah tanggal:sumber
SELECT * FROM theFunction ('2013-06-01', '2013-06-01')
. Tipe data ekspresi masih sama. Dan kedua parameter tersebut adalahdate
tipe data. Bisakah Anda melihat rencana eksekusi?NULL
.CASE
juga tidak berpengaruh, permintaan masih hang.ISNULL
rencana tampak seperti menyederhanakan lebih baik. Ini memiliki predikat kesetaraan sederhana di ColleagueList,[Date]='2013-06-01'
sedangkanCASE
predikatnya ada pada[Date]>='2013-06-01' AND [Date]<=CASE WHEN (1) THEN '2013-06-01' ELSE NULL END AND PROBE([Bitmap1067],[Date])
. Perkiraan baris yang keluar dari gabungan itu adalah 28.393 untukISNULL
versi tetapi jauh lebih rendah di79.8
untukCASE
versi yang mempengaruhi pilihan bergabung nanti dalam rencana. Tidak yakin mengapa ada perbedaan seperti itu.