Sql server 为什么从派生表移动到临时表解决方案时会提高性能?
我正在阅读Grant Fritchey的“剖析SQL Server执行计划”,这对我了解某些查询的速度慢有很大帮助 然而,我被这个简单的重写执行得更快的例子难住了 这是我第一次尝试,需要21秒。它使用一个派生表:Sql server 为什么从派生表移动到临时表解决方案时会提高性能?,sql-server,sql-execution-plan,database-performance,Sql Server,Sql Execution Plan,Database Performance,我正在阅读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 O
-- 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执行计划:
编辑1
当我在group by中指定的2列上创建统计数据时,优化器在放弃过程缓存后开始做“正确的事情”(如果您是初学者,请不要忘记!)。我简化了问题中的查询,回想起来,这不是一个很好的简化。所附的sqlplan显示了这两列,但这并不明显
现在的估计更精确,性能与临时表解决方案相当。正如您所知,优化器会自动在单个列上创建统计信息(如果未禁用),但DBA必须创建两列统计信息
这两列上的(非聚集的)索引使查询执行相同的操作,但在本例中,stat也一样好,并且不会受到索引维护的不利影响。 我将继续使用2列统计数据,看看它的性能如何@Grant你知道索引上的统计数据是否比列统计数据更可靠吗 编辑2 我总是在问题解决后跟进如何在将来更快地诊断类似问题 这里的问题是,估计的路权是一种方式。当您将鼠标悬停在一行上时,图形执行计划将显示这些,仅此而已 一些有帮助的工具:您好,Tom查看第一个执行计划的值,它看起来像是统计数据。估计行数为800,实际行数为120万。我想您会发现,更新统计信息将改变第一个查询计划的生成方式。如果没有两个查询的查询计划,我们无法说出原因。这可能与在派生表上错误估计的临时表上具有准确的统计信息有关。在第一个示例中,将子查询的结果选择到临时表中的目的是什么?为什么不在子选择中按col1拥有COUNT(*)>1的col1从表1 GROUP中选择col1呢?我看不到计划,只有图形。如果没有计划本身,我只能猜测到底发生了什么。要看的是,第一个计划提前终止的原因是什么?用于加载到临时表的表上的统计信息是什么?如果统计数据已经过时,那么加载到temp表可以为您提供更干净的统计数据集。再一次,只要看看图表,这些都是猜测。+1格兰特。在第一个查询中,该计划显示一个哈希连接,但是两个集群扫描的管道宽度看起来几乎相同。对于散列连接,我希望一个管道很小,另一个管道很大。对我来说,这意味着过时或缺少统计数据,这会导致次优计划(联接算法选择不当,为排序和联接预先分配的内存不足,等等)。正如格兰特指出的,这张图并没有完全解释计划(估计的行数,实际的行数…。@buckley仅仅统计数据和索引中的统计数据之间没有差异。它们都是统计数据。我们更新了所有的统计数据,但估计值仍然不准确。我仍然认为这与糟糕的统计数据有关。你知道我们下一步要看什么吗?你用完整扫描更新了统计数据了吗?如果您进行了采样更新,它可能仍然会显示差异。如果没有,那么还有一些我从计划中看不到的事情正在发生。使用完整扫描在表上创建统计数据并没有改善执行计划。您是对的,SQL Server没有正确的评估来制定好的执行计划。我用答案更新了这个问题。