sql >> Databasteknik >  >> RDS >> Sqlserver

välj prestandaförsämring när du använder DISTINCT med parametrar

Problemet är inte att DISTINCT orsakar en prestandaförsämring med parametrar, det är att resten av frågan inte optimeras bort i den parametriserade frågan eftersom optimeraren inte bara kommer att optimera bort alla kopplingar med [email protected] _ADMINISTRATOR gillar det med bara 1=1. Det kommer inte att optimera sammanfogningarna bort utan distinkt eftersom den behöver returnera dubbletter baserat på resultatet av sammanfogningarna.

Varför? Eftersom exekveringsplanen som kastar bort alla kopplingar skulle vara ogiltigt för något annat värde än @IS_ADMINISTRATOR =1. Den kommer aldrig att generera den planen oavsett om du cachar planer eller inte.

Detta fungerar lika bra som den icke-parametriserade frågan på min 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

Det som framgår av frågeplanen som jag ser som kör ditt exempel är att @IS_ADMINISTRATOR = 1 optimeras inte på samma sätt som 1=1 . I ditt icke-parametriserade exempel är JOINS helt optimerade, och det returnerar bara varje ID i DOCUMENTS-tabellen (mycket enkelt).

Det saknas också olika optimeringar när @IS_ADMINISTRATOR <> 1 . Till exempel, LEFT OUTER JOIN S ändras automatiskt till INNER JOIN s utan den där OR sats, men de lämnas som de är med det eller klausul.

Se även detta svar:SQL LIKE % FÖR INTEGERS för ett dynamiskt SQL-alternativ.

Naturligtvis förklarar detta inte riktigt prestandaskillnaden i din ursprungliga fråga, eftersom du inte har OR där inne. Jag antar att det var ett förbiseende.



  1. bra postgresql-klient för Windows?

  2. Extrahera veckonummer från ett datum i SQL Server (T-SQL)

  3. Gå till postgresql LIKE-frågan

  4. Hur går man med i kategoritabell för föräldrar i SQL-fråga?