我编写了一个表值 UDF,它以 CTE 开头,以从大表中返回行的子集。CTE 中有几个连接。几个内连接和一个左连接到其他表,这些表不包含很多行。CTE 有一个 where 子句,它返回一个日期范围内的行,以便只返回需要的行。
然后,我在 4 个自左连接中引用此 CTE,以便使用不同的标准构建小计。
查询非常复杂,但这里是它的简化伪版本
WITH DataCTE as
(
SELECT [columns] FROM table
INNER JOIN table2
ON [...]
INNER JOIN table3
ON [...]
LEFT JOIN table3
ON [...]
)
SELECT [aggregates_columns of each subset] FROM DataCTE Main
LEFT JOIN DataCTE BananasSubset
ON [...]
AND Product = 'Bananas'
AND Quality = 100
LEFT JOIN DataCTE DamagedBananasSubset
ON [...]
AND Product = 'Bananas'
AND Quality < 20
LEFT JOIN DataCTE MangosSubset
ON [...]
GROUP BY [
我感觉 SQL Server 感到困惑并为每个自连接调用 CTE,这似乎通过查看执行计划得到证实,尽管我承认不是阅读这些的专家。
我会假设 SQL Server 足够聪明,只能从 CTE 执行一次数据检索,而不是多次执行。
我尝试了相同的方法,但没有使用 CTE 来获取数据子集,而是使用了与 CTE 中相同的选择查询,但将其输出到临时表。
引用 CTE 版本的版本需要 40 秒。引用临时表的版本需要 1 到 2 秒。
为什么 SQL Server 不够智能,无法将 CTE 结果保存在内存中?
我喜欢 CTE,尤其是在这种情况下,因为我的 UDF 是一个表值的,所以它允许我将所有内容保存在一个语句中。
要使用临时表,我需要编写一个值为 UDF 的多语句表,我发现它是一个稍微不那么优雅的解决方案。
你们中的一些人是否在 CTE 中遇到过这种性能问题,如果有,你们是如何解决这些问题的?
谢谢,
卡洛斯