我有以下链接的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
答案 0 :(得分:4)
很明显,正如您自己所显示的那样。
为什么?最明显的原因是优化器知道临时表的大小。这为优化查询提供了更多信息。 CTE只是估算值。因此,您看到的改进归功于查询计划。
另一个原因是如果在查询中多次引用了CTE。 SQL Server没有实现CTE,因此定义代码将多次运行。
有时,您有意将CTE实例化为临时表,以便可以向它们添加索引。这样也可以提高性能。
所有这些,我宁愿避免使用临时表。优化器通常非常好。
答案 1 :(得分:2)
这取决于许多因素。如果可以,请始终尝试编写单个语句。过早的优化是很多邪恶的根源。
如果您确实遇到了性能问题,那么分解单个语句有一些优点:
答案 2 :(得分:1)
考虑cte1昂贵
;WITH CTE1
AS(
SELECT * FROM TableA
)
SELECT * INTO #Temp FROM CTE1
以上保证cte1只运行一次。
链接的cte可以多次评估cte1。
即使使用#temp,也应考虑使用索引/ PK并对插入进行排序。