Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

изберете влошаване на производителността на отчета, когато използвате DISTINCT с параметри

Проблемът не е, че DISTINCT причинява влошаване на производителността с параметри, а че останалата част от заявката не е оптимизирана в параметризираната заявка, защото оптимизаторът няма просто да оптимизира всички съединения, използвайки [email protected] _ADMINISTRATOR като че ли само с 1=1. Няма да оптимизира присъединяванията без различен, защото трябва да върне дубликати въз основа на резултата от обединенията.

Защо? Тъй като планът за изпълнение, изхвърлящ всички съединения, би бил невалиден за всяка стойност, различна от @IS_ADMINISTRATOR =1. Той никога няма да генерира този план, независимо дали кеширате планове или не.

Това работи толкова добре, колкото и непараметризираната заявка на моя сървър 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

Това, което става ясно от плана на заявката, който виждам, изпълнявайки вашия пример, е, че @IS_ADMINISTRATOR = 1 не се оптимизира по същия начин като 1=1 . Във вашия непараметризиран пример JOINS са напълно оптимизирани и просто връща всеки идентификатор в таблицата DOCUMENTS (много просто).

Липсват и различни оптимизации, когато @IS_ADMINISTRATOR <> 1 . Например LEFT OUTER JOIN S се променят автоматично на INNER JOIN s без това OR клауза, но те са оставени такива, каквито са с това или клауза.

Вижте също този отговор:SQL LIKE % ЗА ЦЕЛИ ЧИСЛА за динамична SQL алтернатива.

Разбира се, това всъщност не обяснява разликата в производителността във вашия първоначален въпрос, тъй като нямате OR там. Предполагам, че това е пропуск.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да зададете стойност по подразбиране за съществуваща колона

  2. Създайте база данни на SQL Server с SQLOPS

  3. Sql сървър - свържете се с удостоверяване на Windows

  4. Грешка 101 „Запитването не е позволено в изчакване“ в SQL Server

  5. Използване на sp_help_schedule в SQL Server