Het probleem is niet dat DISTINCT een prestatievermindering veroorzaakt met parameters, het is dat de rest van de query niet weg wordt geoptimaliseerd in de geparametriseerde query omdat de optimizer niet alleen alle joins optimaliseert met [email protected] _ADMINISTRATOR zoals het hoort met slechts 1=1. Het zal de samenvoegingen niet optimaliseren zonder onderscheiden omdat het duplicaten moet retourneren op basis van het resultaat van de samenvoegingen.
Waarom? Omdat het uitvoeringsplan dat alle joins weggooit, ongeldig zou zijn voor elke andere waarde dan @IS_ADMINISTRATOR =1. Het zal dat plan nooit genereren, ongeacht of u plannen in de cache plaatst of niet.
Dit presteert net zo goed als de niet-geparametriseerde query op mijn 2008-server:
-- 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
Wat duidelijk is uit het queryplan dat ik in uw voorbeeld zie uitvoeren, is dat @IS_ADMINISTRATOR = 1
wordt niet op dezelfde manier geoptimaliseerd als 1=1
. In uw niet-geparametriseerde voorbeeld zijn de JOINS volledig geoptimaliseerd en retourneert het gewoon elke id in de DOCUMENTS-tabel (heel eenvoudig).
Er ontbreken ook verschillende optimalisaties wanneer @IS_ADMINISTRATOR <> 1
. Bijvoorbeeld de LEFT OUTER JOIN
S worden automatisch gewijzigd in INNER JOIN
s zonder dat OR
clausule, maar ze blijven zoals ze zijn met die of clausule.
Zie ook dit antwoord:SQL LIKE % VOOR INTEGERS voor een dynamisch SQL-alternatief.
Dit verklaart natuurlijk niet echt het prestatieverschil in uw oorspronkelijke vraag, omdat u de OK daar niet hebt. Ik neem aan dat dat een vergissing was.