我已经编写了一个UDF以在ETL清理过程中重复使用,并且正在尝试量化哪种方法更好。我想知道我的假设是否正确,即CTE将在调用时计算一个值并将其具体化,但担心它可能只是抽象了多次运行的计算。
要考虑的示例代码:
with cte as (select 'This is a test////////$$$$$$$$' as val),
cteReplaceDollar as (select replace(val, '$', '') as val from cte),
cteReplaceSlash as (select replace(val, '/', '') as val from cteReplaceDollar),
cteReplaceEmpty as (select replace(val, ' ', '') as val from cteReplaceSlash)
select
*
from
cteReplaceEmpty
where
val = 'Thisisatest' and
val > '' and
isnumeric(val) = 0;
这是执行替换3次(乐观假设)还是18次(悲观假设)?基本上,它是实现类似于变量赋值的中间步骤,还是用作生成器表达式,其中对值的每个引用和集合中的每个值执行每个步骤?
答案 0 :(得分:4)
通常,相对于Postgres,SQL Server不会实现CTE。
您可以通过检查查询的实际执行计划来确认。 我建议使用SentryOne Plan Explorer,它是一个很棒的工具。
https://www.sentryone.com/plan-explorer
在您的示例中,我希望看到7个对replace
的呼叫。
好吧,我算错了。真正的答案是:
您应该检查实际的执行计划。
在您的示例中,它看起来像这样:
在replace
运算符中有9个对Filter
的呼叫。
在Compute Scalar
运算符中加上3个呼叫。
12个。
因此,我们确认在此示例中SQL Server没有实现CTE。 (那是SQL Server 2017 Developer Edition)
一些进一步的阅读:
What's the difference between a CTE and a Temp Table?
Is there a performance difference between CTE , Sub-Query, Temporary Table or Table Variable?
Use of With Clause in SQL Server
Microsoft建议微软为CTE添加Materialize
提示,类似于Oracle提供的服务:T-SQL Common Table Expression "Materialize" Option