sql >> Base de Datos >  >> RDS >> Sqlserver

seleccione la degradación del rendimiento de la declaración cuando se usa DISTINCT con parámetros

El problema no es que DISTINCT esté causando una degradación del rendimiento con los parámetros, es que el resto de la consulta no se está optimizando en la consulta parametrizada porque el optimizador no solo optimizará todas las uniones usando [email protected] _ADMINISTRATOR como lo hará con solo 1=1. No optimizará las uniones lejos sin distinto porque necesita devolver duplicados en función del resultado de las uniones.

¿Por qué? Porque el plan de ejecución descartando todas las uniones no sería válido para cualquier valor que no sea @IS_ADMINISTRATOR =1. Nunca generará ese plan, independientemente de si está almacenando planes en caché o no.

Esto funciona tan bien como la consulta no parametrizada en mi servidor 2008:

-- 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

Lo que está claro del plan de consulta que veo al ejecutar su ejemplo es que @IS_ADMINISTRATOR = 1 no se optimiza igual que 1=1 . En su ejemplo no parametrizado, los JOINS están completamente optimizados y solo devuelve cada ID en la tabla DOCUMENTOS (muy simple).

También faltan diferentes optimizaciones cuando @IS_ADMINISTRATOR <> 1 . Por ejemplo, LEFT OUTER JOIN S se cambian automáticamente a INNER JOIN s sin que OR cláusula, pero se dejan tal cual con esa o cláusula.

Vea también esta respuesta:SQL LIKE % FOR INTEGERS para una alternativa SQL dinámica.

Por supuesto, esto realmente no explica la diferencia de rendimiento en su pregunta original, ya que no tiene el OR allí. Supongo que fue un descuido.