Der*_*sar 7 sql-server optimization execution-plan sql-server-2014 parameter-sniffing
好的,所以我有一个我们在 SSRS 报告中使用的非存储过程查询。这个查询非常慢(过去两个小时我已经运行了这个查询的原始版本,但仍未完成),为了改进它,我从头开始重写它,我想出了以下内容:
现在这里是无聊的单词问题部分:
我们希望为TOP 5
每个销售代表提取一份客户列表,但从该列表中排除所有TOP 10
客户。(因此,如果 John Doe 有客户 A、B、C、D 和 E,而客户 C 是前 10 名之一,则只提取 A、B、D 和 E。)
为此,第一个查询使用了IN (... NOT IN ( ) )
,所以我认为是嵌套IN
的问题,为了重写它,我做了一个OUTER APPLY
真正打破一切的查询。
无论如何,我修复了所有这些并运行了查询,但仍然需要 10-15 秒,我认为这是参数嗅探。为了进行调查,我在 SSMS 中运行了查询,添加了OPTION (RECOMPILE)
(查看会生成什么查询计划),并得到以下内容:
可以在 Brent Ozar 的“粘贴计划”中查看此处。生成这个的查询是:
DECLARE @Top10Temp TABLE (Id INT)
INSERT INTO @Top10Temp
SELECT TOP 10 Id
FROM Object1
WHERE Column2 = @ReportId
AND Column3 = 0
GROUP BY Id
ORDER BY SUM(Column4 + Column5) DESC
SELECT Object2.*
FROM Object1 AS Object2
OUTER APPLY (
SELECT TOP 5
Object3.Id,
SUM(Object3.Column4 + Object3.Column5) AS Column6
FROM Object1 AS Object3
WHERE Object3.Column3 = 0
AND Object3.Column7 = Object2.Column7
AND Object3.Column2 = @ReportId
GROUP BY
Object3.Id
ORDER BY
SUM(Object3.Column4 + Object3.Column5) DESC
) AS Object4
WHERE Object2.Column2 = @ReportId
AND Object2.Column3 = 0
AND Object2.Id = Object4.Id
AND Object2.Id NOT IN (SELECT Id FROM @Top10Temp)
ORDER BY Object2.Column7
OPTION (RECOMPILE)
Run Code Online (Sandbox Code Playgroud)
现在是相同的查询,但OPTION (OPTIMIZE FOR UNKNOWN)
生成了以下计划:
也可以在“粘贴计划”中查看。该计划在不到 1 秒内执行完毕。
如果我补充OPTION (OPTIMIZE FOR (@ReportId = #))
,这里#
是相同的@ReportId
变量,我得到相同的查询计划,作为第二。
我做错什么了吗?我无法理解发生了什么,因此非常感谢您提供任何信息。(我也真的不喜欢试图通过提示影响优化器,但如果有必要,我会保留它。)
“为了调查,我在 SSMS 中运行了查询......”这就是问题所在。局部变量使用统计的密度向量产生更好的行估计,因此已经优化了 UNKNOWN。参数化动态 SQL 使用直方图,它提取给定部分的整个行数。
查看每个粘贴计划链接的估计行数与实际行数。第二个链接比第一个链接有更好的估计。
我会将您的 SSRS 查询部署到开发实例并运行一些测试,因为我怀疑您可能遇到性能问题。
顺便说一句,如果可以的话,更新统计信息或重建这些野兽表上的索引。
链接: 在统计直方图和密度向量中
归档时间: |
|
查看次数: |
1458 次 |
最近记录: |