次のEXCEPTクエリは、一見無意味な投影の論理プランを作成します。これはINTERSECTでも発生します。
予測の目的は何ですか?例えば外部投影が何かを指定する別のEXCEPTクエリはありますか?
クエリ:
use AdventureWorks2017
select p.ProductId
from Production.Product as p
except
select pinv.ProductID
from Production.ProductInventory as pinv
option (recompile, querytraceon 8605, querytraceon 3604)
変換されたツリー:
LogOp_Select
LogOp_GbAgg OUT(QCOL: [p].ProductID,) BY(QCOL: [p].ProductID,)
LogOp_Project -- << ?? PASSIVE PROJECTION ??
LogOp_Project
LogOp_Get TBL: Production.Product(alias TBL: p) Production.Product TableID=482100758 TableReferenceID=0 IsRow: COL: IsBaseRow1000
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList
ScaOp_Exists
LogOp_Select
LogOp_Project
LogOp_Get TBL: Production.ProductInventory(alias TBL: pinv) Production.ProductInventory TableID=914102297 TableReferenceID=0 IsRow: COL: IsBaseRow1001
AncOp_PrjList
ScaOp_Comp x_cmpEq
ScaOp_Identifier QCOL: [p].ProductID
ScaOp_Identifier QCOL: [pinv].ProductID
クエリオプティマイザーの内部では、外部で説明できる理由が実際にはないさまざまな処理があります。オプティマイザに表示されるプロジェクトは、最終的にはオプティマイザの最後に書き直され、式を「平坦化」します。したがって、オプティマイザには、コードの実装方法の一部である検索結果があり、実際には何も機能せず、オプティマイザの一部で1つのサブツリーが作成された場所に、プロジェクトを統合することができます。しかし、当初は意図されていなかった場所で後で使用されます。これを引き起こす可能性のある物理的な実装の詳細がいくつかあります。それらのどれも計画品質の点でユーザーにとって重要ではありません(ほとんどすべての場合-検索でこれらを重要ではないようにする作業を行いました)。
だから、私はただ手を振って、「彼の身元を確認する必要はありません。彼は彼の仕事に取り掛かることができます。一緒に進んでください」と言います。
これに対する完全な満足のいく答えはありませんが、DISTINCT
はプロジェクトとgroup-by集約に変換されます。
EXCEPT
とINTERSECT
はどちらも、最初のテーブル式に暗黙のDISTINCT
が付いています。このDISTINCT
がツリーの「空の」プロジェクトになります。無害です。
DISTINCT
を同等のGROUP BY
として記述した場合、空のプロジェクトは表示されません。集計の後にプロジェクトが表示されます。
SELECT DISTINCT P.ProductID
FROM Production.Product AS P
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);
LogOp_GbAgg OUT(QCOL: [P].ProductID,) BY(QCOL: [P].ProductID,)
LogOp_Project
LogOp_Project QCOL: [P].ProductID
LogOp_Get TBL: Production.Product(alias TBL: P)
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList
SELECT P.ProductID
FROM Production.Product AS P
GROUP BY p.ProductID
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8605);
LogOp_Project QCOL: [P].ProductID
LogOp_GbAgg OUT(QCOL: [P].ProductID,) BY(QCOL: [P].ProductID,)
LogOp_Project
LogOp_Get TBL: Production.Product(alias TBL: P)
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList