Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 自联接中引用的SQL Server CTE速度较慢_Sql Server_Performance_Temp Tables_Common Table Expression - Fatal编程技术网

Sql server 自联接中引用的SQL Server CTE速度较慢

Sql server 自联接中引用的SQL Server CTE速度较慢,sql-server,performance,temp-tables,common-table-expression,Sql Server,Performance,Temp Tables,Common Table Expression,我编写了一个表值UDF,它以CTE开头,从一个大表返回行的子集。 CTE中有几个连接。两个内部表和一个左侧表连接到其他表,这些表不包含很多行。 CTE有一个where子句,它返回日期范围内的行,以便只返回所需的行 然后我在4个自左连接中引用这个CTE,以便使用不同的标准构建小计 该查询相当复杂,但这里是它的简化伪版本 WITH DataCTE as ( SELECT [columns] FROM table INNER JOIN table2

我编写了一个表值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中相同的select查询,而是将其输出到临时表

引用CTE版本的版本需要40秒。参考临时表的版本需要1到2秒

为什么SQL Server不够智能,无法将CTE结果保存在内存中

我喜欢CTE,尤其是在这种情况下,因为我的UDF是表值的,所以它允许我将所有内容保存在一个语句中

要使用临时表,我需要编写一个多语句表值UDF,我发现这是一个稍微不那么优雅的解决方案

你们中的一些人在CTE上有过这样的性能问题吗?如果有,你们是如何解决的

谢谢


哈洛斯

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

另一个好处是,您可以在临时表上创建索引,而不能对cte创建索引。不确定在你的情况下是否会有好处,但很高兴知道

相关阅读:

引用最后一个链接:

CTE的基础查询将是 每次在中引用时调用 紧跟其后的查询

我要说的是和临时表一起去。不幸的是,优雅并不总是最好的解决方案

更新:

嗯,这让事情变得更困难了。如果不看看你的整个环境,我很难说

一些想法:

是否可以使用存储过程而不是UDF,而不是从内部使用? 这可能不可能,但如果可以从CTE中删除左连接,则可以将其移动到索引视图中。如果您能够做到这一点,您可能会看到性能甚至超过临时表。
你能发布你的执行计划吗?非常感谢这些伟大的参考资料。那就是我当时的想法。。。正如你所说,我将不得不放弃优雅,让这个UDF花费40秒不是一个选项。我希望它将在SQL Server的下一个版本中得到优化。。。在那之前,我可能会倾向于避免CTE。。。至少,有了一张临时的桌子,我能感觉到更多地控制幕后发生的事情。再次感谢。啊。。。我忘记了,即使是多状态UDF也不能使用临时表。我尝试过使用表变量,但是性能非常糟糕。。。甚至比CTE版本更糟糕。。。我的数据子集大约有10000行,但根据用户提供的参数,可以增加到100000行。考虑到必须将数据作为表返回给调用者,我的其他选择是什么。谢谢。看我的更新。不幸的是,我觉得这两个都不适合你。