Masalahnya bukan karena DISTINCT menyebabkan penurunan kinerja dengan parameter, tetapi sisa kueri tidak dioptimalkan dalam kueri berparameter karena pengoptimal tidak hanya akan mengoptimalkan semua gabungan menggunakan [email protected] _ADMINISTRATOR menyukainya hanya dengan 1=1. Itu tidak akan mengoptimalkan gabungan tanpa berbeda karena perlu mengembalikan duplikat berdasarkan hasil gabungan.
Mengapa? Karena rencana eksekusi membuang semua gabungan akan menjadi tidak valid untuk nilai apa pun selain @IS_ADMINISTRATOR =1. Itu tidak akan pernah menghasilkan rencana itu terlepas dari apakah Anda sedang menyimpan rencana atau tidak.
Ini berfungsi sebaik kueri yang tidak berparameter di server 2008 saya:
-- PARAMETRIZED QUERY
declare @IS_ADMINISTRATOR int
declare @User_ID int
set @IS_ADMINISTRATOR = 1 -- 1 for administrator 0 for normal
set @User_ID = 50
IF 1 = @IS_ADMINISTRATOR
BEGIN
SELECT DISTINCT -- PLEASE REMEMBER DISTINCT MAKES THE DIFFERENCE!!!
DOC.DOCUMENT_ID
FROM
DOCUMENTS DOC LEFT OUTER JOIN
FOLDERS FOL ON FOL.FOLDER_ID = DOC.FOLDER_ID LEFT OUTER JOIN
ROLES ROL ON (FOL.FOLDER_ID = ROL.FOLDER_ID)
WHERE
1 = 1
END
ELSE
BEGIN
SELECT DISTINCT -- PLEASE REMEMBER DISTINCT MAKES THE DIFFERENCE!!!
DOC.DOCUMENT_ID
FROM
DOCUMENTS DOC LEFT OUTER JOIN
FOLDERS FOL ON FOL.FOLDER_ID = DOC.FOLDER_ID LEFT OUTER JOIN
ROLES ROL ON (FOL.FOLDER_ID = ROL.FOLDER_ID)
WHERE
ROL.USER_ID = @USER_ID
END
Yang jelas dari paket kueri yang saya lihat menjalankan contoh Anda adalah @IS_ADMINISTRATOR = 1
tidak dioptimalkan sama dengan 1=1
. Dalam contoh non-parameter Anda, GABUNG sepenuhnya dioptimalkan, dan hanya mengembalikan setiap id dalam tabel DOKUMEN (sangat sederhana).
Ada juga pengoptimalan berbeda yang hilang saat @IS_ADMINISTRATOR <> 1
. Misalnya, LEFT OUTER JOIN
S secara otomatis diubah menjadi INNER JOIN
s tanpa bahwa OR
klausa, tetapi dibiarkan apa adanya dengan itu atau klausa.
Lihat juga jawaban ini:SQL LIKE % UNTUK INTEGER untuk alternatif SQL dinamis.
Tentu saja, ini tidak benar-benar menjelaskan perbedaan kinerja dalam pertanyaan awal Anda, karena Anda tidak memiliki OR di sana. Saya berasumsi bahwa itu adalah kekhilafan.