这里是使用表值函数的结果的合并:
MERGE
Table1 d
USING
dbo.tvf_Table1(@StartDate, @EndDate) s ON d.ID = s.ID
WHEN MATCHED THEN UPDATE
SET Dest1 = Src1, Dest2 = Src2, Dest3 = Src3
WHEN NOT MATCHED THEN INSERT
VALUES(ID, Src1, Src2, Src3);
在我的环境中,该过程大约花费了30秒(三次运行的平均值)。
这里是相同的MERGE,但这一次将函数结果放在临时表中:
SELECT
*
INTO
#Temp1
FROM
dbo.tvf_Table1(@StartDate, @EndDate)
MERGE
Table1 d
USING
#Temp1 s ON d.ID = s.ID
WHEN MATCHED THEN UPDATE
SET Dest1 = Src1, Dest2 = Src2, Dest3 = Src3
WHEN NOT MATCHED THEN INSERT
VALUES(ID, Src1, Src2, Src3);
DROP TABLE #Temp1
大约花费了31秒(平均三遍)。
事实上,使用临时表运行54个以上的MERGE大约要比不使用临时表快四分钟。
接受到这几乎是不科学的,我希望添加临时表步骤会大大降低查询速度。毕竟,数据是从A移到B,然后是从B移到C,而不是直接从A移到C。
可能导致这种情况的幕后原因是什么?
答案 0 :(得分:2)
与表值函数相比,临时表为优化器提供了更多优化信息。
我很高兴您希望写入表的开销会减慢整体速度。但是,合并查询的其余部分也需要进行优化,知道表的确切大小有助于优化器改善总体计划。
答案 1 :(得分:0)
提供给临时表的数据量不是太大,服务器应该能够将所有数据保留在内存中,而不必将其溢出到磁盘上。因此,与B
相比,A
-> B
,B
-> C
中的C
非常便宜A
)。通常,您希望I / O成本会在直接查询中淹没其他大多数成本。
在宏伟的计划中,如果单个MERGE
的性能足够好,我还是会比较喜欢它。不要试图通过将任务分解为一系列子任务来帮助SQL Server-这是优化程序的工作,尽管它可能并不总是选择最佳计划,但通常会选择一个足够好的计划。