我刚刚将我们的数据仓库升级到 SQL 2016。我在查询存储中看到了一些非常有趣的图表(我喜欢这个功能!)。下面是我见过的最奇怪的例子。同一查询的 22 个计划。
这让我开始考虑 ETL 流程的性能调整、临时表的优缺点以及如何影响执行计划的行为。
我的 ETL 过程使用了许多存储过程,它们混合使用标准和临时 #tables 作为临时表。#tables 通常使用一次然后删除。有些只有几千行。有些是数百万。SSMS 建议缺少索引,但在较小的表上,它们是否会产生足够的差异以值得努力添加它们?更好的统计数据就足够了吗?
我刚刚阅读了有关临时表统计信息的 Brent Ozar 博客文章,以及 Paul White 关于存储过程中的临时表的文章
它说统计信息是在查询#table 时自动创建的,然后可能会被优化器使用。
我的问题是:在#table 上创建索引有什么意义或好处。和/或:是否值得在查询中使用之前显式更新统计信息作为存储过程中的一个步骤,因为它们只使用一次。
额外的步骤和开销值得吗?它会导致明显更好或不同的执行计划吗?
在临时表上创建索引可能有好处,但对于临时表可能没有。不幸的是,这是一个“取决于”的答案。您将需要进行测试。如果您发布了有关如何与临时表交互的代码,我们可以帮助确定是否有任何索引会有所帮助。如果您将临时表连接到另一个表,则索引可能会有所帮助的一个示例。如果您要索引连接的列,可能会提高性能,尤其是在临时表中有很多行的情况下。
您可能不需要更新临时表的统计信息。这也是一个“取决于”的答案,尽管我从未在我查看过的成千上万个存储过程中的任何一个中看到临时表的更新统计信息,也不需要添加它来解决性能问题。
仅有统计数据是不够的。存储引擎必须有某种方式来获取与查询谓词匹配的行。如果无法确定表中的一百万行中的三行是哪三行,那么知道三行与条件匹配是没有价值的。如果没有索引,唯一的策略是表扫描。将读取一百万行。99.9997% 将被丢弃。使用匹配的索引,可以按照指针来挑选所需的三行。
对于只需要几页的小表,必须考虑读取索引页的工作量。假设一个与查询完全匹配的非聚集索引只需要两个级别。那是两个页面读取跟随键。然后是聚集索引。那很可能是多读两页。因此,如果整个表的页数少于 4 页,则非聚集索引不太可能被使用。