Примечание для вознаграждения - НАЧАЛО:
ПАРАМЕТРЫ СНИФФИНГА (это единственная «идея», о которой сообщалось в вопросах перед наградой), здесь не проблема, как вы можете прочитать в разделе «обновление» в конце вопроса. Проблема действительно связана с тем, как сервер sql создает планы выполнения для параметризованного запроса, когда используется отдельный.
Я загрузил очень простую резервную копию базы данных (она работает с SQL Server 2008 R2) здесь (вы должны подождать 20 секунд перед загрузкой). В отношении этой БД вы можете попробовать выполнить следующие запросы:
-- PARAMETRIZED QUERY
declare @IS_ADMINISTRATOR int
declare @User_ID int
set @IS_ADMINISTRATOR = 1 -- 1 for administrator 0 for normal
set @User_ID = 50
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 = @IS_ADMINISTRATOR OR ROL.USER_ID = @USER_ID
-- NON PARAMETRIZED QUERY
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 OR ROL.USER_ID = 50
Последнее замечание: я заметил, что проблема в DSTINCT, моя цель - добиться одинаковой скорости (или, по крайней мере, почти одинаковой скорости) в обоих запросах.
Примечание для награды - КОНЕЦ:
Оригинальный вопрос:
Я заметил, что есть большая разница в производительности между
-- Case A
select distinct * from table where id > 1
по сравнению с (это sql, сгенерированный моим приложением Delphi)
-- Case B1
exec sp_executesql N'select distinct * from table where id > @P1',N'@P1 int',1
, что эквивалентно
-- Case B2
declare @P1 int
set @P1 = 1
select distinct * from table where id > @P1
A работает намного быстрее, чем B1 и B2. Производительность становится такой же, если я удаляю DISTINCT.
Можете ли вы прокомментировать это?
Здесь я разместил тривиальный запрос, я заметил это на запросе с 3 INNER JOIN. Во всяком случае, не сложный запрос.
Примечание: я ожидал получить ТОЧНУЮ ОДНУ ИСПОЛНИТЕЛЬСКУЮ ЭФФЕКТИВНОСТЬ в случаях A и B1 / B2.
Так есть ли некоторые предостережения в использовании DISTINCT?
UPDATE
Я попытался отключить анализ параметров с помощью DBCC TRACEON (4136, -1)
(флаг, чтобы отключить анализ параметров), но ничего не изменилось. Таким образом, в этом случае проблема не связана с отсчетом параметров. Есть идеи?