赏金注意事项 - 开始:
参数嗅探(这是赏金前问题中报告的唯一“想法”)不是这里的问题,您可以在问题末尾的“更新”部分中阅读。这个问题实际上与sql server在使用distinct时如何为参数化查询创建执行计划有关。
我上传了一个非常简单的数据库备份(它适用于sql server 2008 R2)here(下载前必须等待 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
相比(这是我的 Delphi 应用程序生成的 sql)
-- 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)
(禁用参数嗅探的标志)但没有任何变化。因此,在这种情况下,问题与参数嗅探无关。任何想法?