Saya memiliki SP dengan parameter yang memiliki NULL sebagai nilai default dan kemudian saya ingin melakukan kueri seperti ini:
SELECT ...
FROM ...
WHERE a.Blah = @Blah AND (a.VersionId = @VersionId OR (@VersionId IS NULL AND a.VersionId IS NULL));
The WHERE
atas pemeriksaan untuk kedua nilai non-NULL dan nilai NULL untuk @VersionId
.
Apakah lebih baik dalam hal kinerja daripada menggunakan IF
pernyataan dan menduplikasi kueri menjadi yang mencari NULL dan yang lain untuk NULL seperti itu? :
IF @VersionId IS NULL BEGIN
SELECT ...
FROM ...
WHERE a.Blah = @Blah AND a.VersionId IS NULL;
ELSE BEGIN
SELECT ...
FROM ...
WHERE a.Blah = @Blah AND a.VersionId = @VersionId;
END
Atau optimizer kueri membuatnya pada dasarnya sama?
MEMPERBARUI:
(Catatan: Saya menggunakan SQL Server)
(Dan sejauh yang saya tahu, menggunakan a.VersionId = @VersionId
untuk kedua kasus tidak akan berhasil, kan?)
sql-server-2008
performance
pengguna2173353
sumber
sumber
Jawaban:
Pola ini
dapat diganti dengan
Ini akan memungkinkan Anda mencocokkan NULL dengan NULL dan akan memungkinkan mesin menggunakan indeks secara
column
efisien. Untuk analisis mendalam yang sangat baik dari teknik ini, saya merujuk Anda ke artikel blog Paul White:Karena ada dua argumen dalam kasus khusus Anda, Anda dapat menggunakan teknik pencocokan yang sama dengan
@Blah
- dengan cara itu Anda akan dapat menulis ulang seluruh klausa WHERE secara lebih ringkas:Ini akan bekerja cepat dengan indeks aktif
(a.Blah, a.VersionId)
.Dalam hal ini, ya. Di semua versi (setidaknya) dari SQL Server 2005 dan seterusnya, pengoptimal dapat mengenali pola
col = @var OR (@var IS NULL AND col IS NULL)
dan menggantinya denganIS
perbandingan yang tepat . Ini bergantung pada pencocokan penulisan ulang internal, jadi mungkin ada kasus yang lebih kompleks di mana ini tidak selalu dapat diandalkan.Dalam versi SQL Server dari 2008 SP1 CU5 inklusif , Anda juga memiliki opsi untuk menggunakan Optimasi Penempelan Parameter melalui
OPTION (RECOMPILE)
, di mana nilai runtime dari setiap parameter atau variabel tertanam dalam kueri sebagai literal sebelum kompilasi.Jadi, setidaknya untuk sebagian besar, dalam hal ini pilihannya adalah masalah gaya, meskipun
INTERSECT
konstruksinya tidak dapat disangkal kompak dan elegan.Contoh berikut menunjukkan rencana eksekusi 'sama' untuk setiap variasi (literal versus referensi variabel dikecualikan):
sumber