什么规则决定了 SQL Server 何时使用 CTE 作为“优化栅栏”?

Bry*_*bok 11 performance sql-server optimization cte query-performance

不久前,Brent Ozar 发表了一篇文章,详细介绍了 SQL Server 和 PostgreSQL 之间的一些差异:

SQL Server 和 PostgreSQL 的两个重要区别

第一点(“CTE 是优化栅栏”)引起了我的注意,因为很明显,在提供的示例中,SQL Server 将 CTE 和主查询组合在一起并将其优化为单个查询(而不是在PostgreSQL)。

但是,这种行为似乎与我在其他博客和培训课程中看到的示例相反,其中 SQL Server 确实将 CTE 视为优化栅栏,从而可以更好地使用索引、更好的性能等。例如:

更好的选星方式

因此,似乎 SQL Server 有时“尊重”CTE 作为优化栅栏。是否有任何好的资源可以记录 SQL Server 将可靠地将 CTE 作为优化栅栏(或相反的行为)的已知案例的特定列表?

Pau*_*ite 11

... SQL Server 将可靠地将 CTE 作为优化栅栏的已知案例列表

任何此类列表都将依赖于观察到的行为,不保证可靠性。

SQL Server 查询优化器从不将公共表表达式本身视为优化栅栏,尽管某些结构显然难以优化。递归 CTE 就是一个很好的例子。

CTE 的处理方式与视图/内联函数/子查询/派生表非常相似,并被内联到查询中。任何观察到的“围栏”行为都取决于优化器不能或决定不优化原则上可渗透的边界。

一般来说,CTE 越简单、越“相关”,优化器就越有可能移动位。

已经建议了允许优化器考虑或强制它实现 CTE 的“结果”的功能,但尚未实现:

同时,最常见的解决方法是在临时表或表变量中显式实现中间结果集。这显然需要一个不限于单个语句的场景。