web-dev-qa-db-ja.com

サブクエリはCTEとは異なる実行計画を作成できますか?

私はボスマンと話していましたが、彼は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の奇妙で素晴らしい世界では、答えは常にに依存するようです

3
James

現状のままでは、質問には答えられないと主張します。ネガを証明することは不可能であり、製品ドキュメントで保証が見つかりません。 2つのアプローチの技術的な違いの例が必要な場合は、Paul Whiteの Query Optimizer Deep Dive セッションの数分をご覧ください。誰かがそれをパフォーマンスのベストプラクティスにどのように変換できるかは明らかではありません。

パフォーマンスのベストプラクティスを見つけるのではなく、コーディングスタイルの問題として問題に取り組むことをお勧めします。派生テーブルのCTEまたはCTEの派生テーブルを切り替えることは、クエリを書き換える意味のある方法ではありません。

6
Joe Obbish

一般に、状況によって異なります。 CTEが派生テーブルより優れているケースの1つは、クエリでCTEを複数回参照する必要がある場合です。ばかげた例:

SELECT x,y
FROM (
    SELECT x,y FROM T WHERE p
) AS A
WHERE x = (SELECT MAX(x) FROM T WHERE p)

WITH CTE (x,y) as ( 
    SELECT x,y FROM T WHERE p 
)
SELECT x,y FROM CTE WHERE x = (SELECT MAX(x) FROM CTE)

異なるデータベースエンジンは、CTEへの複数の参照を異なる方法で処理します。 SQL Serverでは、CTEは通常、参照ごとに完全に評価されます。

4
Lennart