我正在和老板交谈,他更喜欢子查询而不是 CTE。就个人而言,我讨厌子查询。他提到子查询可以更快,但我不相信。我进行了这个简短的测试:
with classes as
(select top 10 Classkey from dimclass
group by classkey
order by count(1) desc),
policies as (
select CarrierKey, policykey, periodeffectivedate from dimpolicy),
exposure as (
select policykey, classkey from DimExposure)
select * from policies p
inner join exposure x on p.PolicyKey = x.PolicyKey
inner join classes c on x.ClassKey = c.Classkey
有一个执行计划:
https://www.brentozar.com/pastetheplan/?id=SJYJUZNHS
select p.CarrierKey, p.PolicyKey, p.periodeffectivedate from dimpolicy p
inner join (select policykey, classkey from DimExposure) x on p.PolicyKey = x.PolicyKey
inner join (select top 10 Classkey from dimclass
group by classkey
order by count(1) desc) c on x.ClassKey = c.Classkey
具有相同的执行计划:
https://www.brentozar.com/pastetheplan/?id=rJs_LbVSr
问题:总是这样吗?在 SQL Server 奇异而奇妙的世界中,答案似乎总是视情况而定。
照原样,我认为这个问题是无法回答的。不可能证明是否定的,并且您不会在产品文档中找到保证。如果您想了解两种方法之间技术差异的示例,请观看几分钟的 Paul White 的查询优化器深入探讨会议。目前尚不清楚有人如何将其转化为性能最佳实践。
我建议将问题作为编码风格来解决,而不是试图找到性能最佳实践。为派生表切换 CTE 或为 CTE 切换派生表并不是重写查询的有意义的方式。
一般来说,这取决于。CTE 比派生表更好的一种情况是您需要在查询中多次引用它。一个愚蠢的例子:
对比
不同的数据库引擎以不同的方式处理对 CTE 的多个引用。在 SQL Server 中,通常会针对每个引用对 CTE 进行全面评估。