我正在考虑提高某些SQL的性能,目前CTE在脚本中被多次使用和引用。我会使用表变量来改进吗? (不能使用临时表,因为代码在函数内。)
答案 0 :(得分:6)
你真的要进行性能测试 - 没有是/否答案。根据Andy Living上面链接的帖子,CTE只是查询或子查询的简写。
如果您在同一个函数中调用它两次或更多次,如果填充表变量然后加入/选择该变量,则可能会获得更好的性能。但是,由于表变量在某处占用空间,并且没有索引/统计信息(除了表变量上的任何声明的主键),没有办法说哪个更快。
它们都有成本和节省,这是最好的方式取决于它们引入的数据以及它们用它做什么。我一直在你的情况下,在各种条件下测试速度后 - 一些函数使用CTE,其他函数使用表变量。
答案 1 :(得分:2)
可能不是。 CTE特别擅长查询树结构的数据。
答案 2 :(得分:0)
CTE的优势
CTE可以称为“临时视图”,在某些情况下可以用作视图的良好替代方案。 与视图相比的主要优势是内存的使用。由于CTE的范围仅限于其批次,因此,一旦超过其批次,就会为它分配的内存将被清空。但是,一旦创建视图,它就会被存储直到用户放下它。如果视图在创建后未使用,则仅浪费内存。 与View相比,用于CTE执行的CPU成本更低。 与View一样,CTE不存储其定义的任何元数据,并提供更好的可读性。 在查询中可以多次引用CTE。 由于范围仅限于批处理,因此多个CTE可以具有视图不能拥有的相同名称。 可以使它递归。
CTE的缺点
尽管使用CTE是有优势的,但确实有一些局限性需要牢记, 我们知道它可以替代视图,但不能嵌套CTE,而可以嵌套View。 一次声明的视图可以多次使用,但不能使用CTE。每次要使用它时都应声明它。在这种情况下,不建议使用CTE,因为对于用户来说,一次又一次地声明批次是一项繁琐的工作。 在锚成员之间应该有UNION,UNION ALL或EXCEPT等运算符。 在递归CTE中,您可以定义许多锚成员和递归成员,但是必须在第一个递归成员之前定义所有锚成员。您不能在两个递归成员之间定义锚成员。 列数,锚成员和递归成员中使用的数据类型应相同。 在递归成员中,不允许使用聚合函数(如TOP),运算符(如DISTINCT),子句(如HAVING和GROUP BY),子查询,联接(如Left Outer或Right Outer或Full Outer)。关于联接,递归成员中仅允许内部联接。 递归限制为32767,超过此限制将导致由于无限循环导致服务器崩溃。