我正在阅读Grant Fritchey的“解析SQL Server执行计划”,它帮助我了解为什么某些查询很慢。
但是,我很难理解这种情况,简单的重写速度要快得多。
这是我的第一次尝试,需要21秒。它使用派生表:
-- 21 secs
SELECT *
FROM Table1 AS o JOIN(
SELECT col1
FROM Table1
GROUP BY col1
HAVING COUNT( * ) > 1
) AS i ON ON i.col1= o.col1
我的第二次尝试速度提高了3倍,只需将派生表移出临时表即可。现在它快了3倍:
-- 7 secs
SELECT col1
INTO #doubles
FROM Table1
GROUP BY col1
HAVING COUNT( * ) > 1
SELECT *
FROM Table1 AS o JOIN #doubles AS i ON i.col1= o.col1
我的主要兴趣是为什么从派生表转移到临时表会如此提高性能,而不是如何让它更快。
如果有人能告诉我如何使用(图形)执行计划诊断此问题,我将不胜感激。
Xml执行计划: https://www.sugarsync.com/pf/D6486369_1701716_16980
修改1
当我创建关于group by中指定的 2 列的统计信息并且优化器开始执行“正确的事情”时,放弃过程缓存后(不要忘记,如果你是初学者!)。我简化了问题中的查询,这在回顾中并不是一个很好的简化。附加的sqlplan显示了2列,但这并不明显。
估算现在更加准确,因为性能与临时表解决方案相当。如您所知,优化器会自动在单个列上创建统计信息(如果未禁用),但DBA必须创建2个列统计信息。
这两个列上的(非聚集)索引使查询执行相同但在这种情况下,stat同样好,并且不会遭受索引维护的缺点。 我将继续进行2列统计,看看它是如何运作的。 @Grant你知道索引的统计数据是否比列统计数据更可靠吗?
修改2
一旦问题解决了将来如何更快地诊断出类似问题,我总会跟进。
这里的问题是估计的行数是这样的。当您将鼠标悬停在一行上时,图形执行计划会显示这些内容,但这就是它。
一些可以提供帮助的工具:
我听说这个会变得过时并被其XML变种所取代,但我仍然喜欢网格格式的输出。 这里“Rows”和“EstimateRows”列之间的巨大差异会显示问题
这是一个很好的工具,特别是如果你是初学者。它突出了问题
更通用的工具,但又会引导用户解决潜在的问题
亲切的问候,汤姆
答案 0 :(得分:4)
查看第一个执行计划的值,它看起来像是统计信息。估计行数为800,实际为120万。我想你会发现更新统计信息会改变第一个查询计划的生成方式。