链接的CTE与温度表的性能影响

时间:2018-11-02 17:07:01

标签: sql sql-server tsql sqlperformance sql-cte

我有以下链接的CTE查询(简化):

// existing
var socket = new easyXDM.socket(cfg);

// addon
var My = {
   easyXDM: easyXDM.noConflict("My"), // not working, no easyXDM anymore
   open: function (cfg) {
       this.socket = new this.easyXDM.socket(cfg);
   }
};
My.open(cfg);

如果我断开CTE链并将CTE1的数据存储到临时表中,则整个查询的性能将提高(从1分钟20秒提高到8秒)。

;WITH CTE1
AS(    
    SELECT * FROM TableA
),
CTE2
AS(
    SELECT * FROM TableB b INNER JOIN CTE1 c ON b.id = c.id
)

SELECT * FROM CTE2

CTE1和CTE2中存在复杂的查询。我刚刚创建了一个简化版本以在此处进行说明。

打破CTE主席能否提高绩效?

SQL Server版本:2008 R2

3 个答案:

答案 0 :(得分:4)

很明显,正如您自己所显示的那样。

为什么?最明显的原因是优化器知道临时表的大小。这为优化查询提供了更多信息。 CTE只是估算值。因此,您看到的改进归功于查询计划。

另一个原因是如果在查询中多次引用了CTE。 SQL Server没有实现CTE,因此定义代码将多次运行。

有时,您有意将CTE实例化为临时表,以便可以向它们添加索引。这样也可以提高性能。

所有这些,我宁愿避免使用临时表。优化器通常非常好。

答案 1 :(得分:2)

这取决于许多因素。如果可以,请始终尝试编写单个语句。过早的优化是很多邪恶的根源。

如果您确实遇到了性能问题,那么分解单个语句有一些优点:

  • 它可以通过降低复杂性来提高可维护性,这是许多非功能性要求之一。
  • 只要中间实现的成本和节省的时间少于原始成本,它就能制定出更好的计划。
  • 可以对中间表建立索引。
  • 索引,主键和唯一约束对于优化器非常有用,不仅用于选择联接类型,而且对于估计基数也有很大作用,这对内存授予有很大影响。
  • 您可以选择应用优化程序提示(例如MAXDOP)仅用于选择语句,而不是一个巨大的语句。当您需要操纵内存授予时,这特别有用。
  • 您可以调整单个语句以消除溢出到tempdb。
  • 根据流程的复杂性和总执行时间,您可以更早地释放资源锁,这还取决于您的语句在哪个隔离级别下运行。
  • 如果由于优化器超时而导致查询计划不佳,则使用不太复杂的单个语句可能会产生更好的总体结果。

答案 2 :(得分:1)

考虑cte1昂贵

;WITH CTE1
AS(    
    SELECT * FROM TableA
)

SELECT * INTO #Temp FROM CTE1

以上保证cte1只运行一次。

链接的cte可以多次评估cte1。

即使使用#temp,也应考虑使用索引/ PK并对插入进行排序。