sql >> Database >  >> RDS >> Sqlserver

selecteer prestatievermindering van de verklaring bij gebruik van DISTINCT met parameters

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.



  1. Eenvoudige MySQL-updaterang met banden

  2. query in codeigniter:krijg waar of

  3. Prestaties van RegEx versus LIKE in MySql-query's

  4. Getallen opmaken in Oracle