微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql-server – 在自连接中引用的SQL Server CTE很慢

我编写了一个表值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有这种性能问题,如果是这样,你是如何对它们进行排序的?

谢谢,

Kharlos

解决方法

我相信每次检索CTE结果.使用临时表,结果将被存储,直到被删除.这似乎可以解释您切换到临时表时所看到的性能提升.

一个好处是您可以在临时表上创建索引,而这些索引是您无法对cte执行的.不确定在你的情况下是否会有好处但是很高兴知道.

相关阅读:

> Which are more performant,CTE or temporary tables?
> SQL 2005 CTE vs TEMP table Performance when used in joins of other tables
> http://msdn.microsoft.com/en-us/magazine/cc163346.aspx#S3

从最后一个链接引用:

The CTE’s underlying query will be
called each time it is referenced in
the immediately following query.

我会说与临时表一起去.不幸的是优雅并不总是最好的解决方案.

更新:

嗯,这让事情变得更加困难.看着你的整个环境,我很难说.

一些想法:

>你可以使用存储过程而不是UDF(而不是从内部)?>这可能无法实现,但如果您可以从CTE中删除左连接,则可以将其移动到索引视图中.如果你能够做到这一点,你甚至可以看到性能提升甚至临时表.

原文地址:https://www.jb51.cc/mssql/78221.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐