【发布时间】:2014-06-26 19:52:45
【问题描述】:
我针对需要以多种不同方式收集数据的现有数据库 (SQL2008 - SQL2012) 开发报告。
一个典型的查询可能看起来像
WITH ThisYearData AS (
SELECT ...
)
,LastYearData AS (
SELECT ...
)
,BudgetData AS (
SELECT ...
)
SELECT ...
FROM SomeDateTable
LEFT JOIN ThisYearData
ON ...
LEFT JOIN BudgetData
...
有时 CTE 相互依赖,一个典型的查询涉及其中的 5-10 个。
问题在于,在一小部分数据上运行类似的查询可能需要 1 秒到 5 分钟不等。
性能下降的主要原因是 SQL Server 使用嵌套循环而不是哈希连接。在某些情况下,我可以将HASH JOIN 放在正确的位置,以使查询速度提高 100 倍。在其他情况下,我会将一个或多个 CTE 转换为表变量。
我知道选择嵌套循环而不是散列连接的原因是基于基于统计的估计行数。 在我的情况下,我无权访问数据库架构,因此无法添加索引或统计信息,但我可以确保更新现有统计信息(并启用自动创建/更新统计信息)。
要找到导致减速的嵌套循环,我这样做:
- 查找具有大量行和执行的节点
- 沿着路径向上直到找到正确的嵌套循环
- 找出导致嵌套循环的连接并将其强制为
hash join
(SQL Sentry explorer 让这变得容易多了)
我的问题是:
- 我是否做了一些根本性的错误,导致 SQL Server 几乎总是低估行数(单位数估计和实际以千为单位很常见)
- 执行计划通常会显示一些不相关的表扫描,百分比很高,这不是很有帮助。执行计划中的百分比是多少?我可以将其更改为对我的场景更有帮助吗?
【问题讨论】:
标签: sql-server join sql-execution-plan