估计基数时,优化器如何处理尚未填充的 #temp 表?

Mar*_*tor 9 sql-server temporary-tables cardinality-estimates

我一直在构建存储过程,但找不到任何关于 SQL Server 优化器如何处理 #temp 表的文档。

如果我有 4 个连接到一个 #temp 表,其中该 #temp 表是在存储过程执行期间创建的,并且 #temp 表可能包含零到多个记录,如何估计?

估计和join中的一些表一样大,因为在CREATE/ALTER的时候没有统计?估计很小?估计和其他#temporary表一样吗?

请注意,这是假设在执行时没有重新编译并且使用原始的。

Pau*_*ite 13

SQL Server 通常在存储过程开始执行之前为存储过程中的语句构建一套完整的执行计划。

当存在临时表时,该方法略有修改:

  • 引用临时表的每个语句的编译被推迟到该语句被实际执行。
  • SQL Server从 2005 版开始就支持语句级重新编译。仅重新编译受影响的语句;手术计划的其余部分不受影响。
  • 延迟编译意味着 SQL Server在优化期间知道临时表的运行时基数
  • SQL Server 还可以自动创建统计信息以支持正在编译的查询。这发生在编译期间,从技术上讲会导致重新编译。
  • 因此,构建的执行计划受益于准确的基数信息自动创建的统计对象(如果启用了该选项)。

这是基本的大纲,但不是整个故事。

正如在另一个答案中已经指出的那样,存储过程中的临时表也可能被缓存以供重用。这种缓存可以显着提高性能和可伸缩性,但它确实使计划重新编译的条件以及如何维护统计信息变得复杂。

我在Temporary Table Caching ExplainedTemporary Table Caching in Stored Procedures 中为感兴趣(和高级)的读者描述了这些额外的复杂性。

  • @MarkAdamProctor 不,我不这么认为。它就在那里,但不是很容易被发现。在接下来的一段时间内,我将添加一些基本要素的文档链接。 (2认同)

Han*_*non 8

粗略地说,在#temp 表上创建统计信息的基数估计遵循常规、非临时表的基数估计。话虽如此,正如Paul White这里指出的那样,存储过程中的临时表可能会受到缓存统计值的影响。

从上面的页面,突出的要点是:

存储过程中的临时表有许多意想不到的特征:

  • 尽管有显式的 CREATE 和 DROP 语句,但临时对象可能会在执行过程中被缓存
  • 与缓存的临时对象关联的统计信息也被缓存
  • 与临时表的当前内容相比,统计信息可能是 100% 错误的
  • 过程结束时的隐式 TRUNCATE TABLE 对列修改计数器的预期影响加倍
  • 可以在创建它们的语句之前更新缓存的统计信息
  • OPTION (RECOMPILE) 改变了在过程调用之间进行列修改的方式
  • 手动 UPDATE STATISTICS 不足以强制重新编译

我建议看一下这篇文章,以彻底了解您可能会如何受到临时表缓存的影响。