SQL Serverのカバーの下でExcept演算子がどのように機能するかの内部アルゴリズムは何ですか?
には特別な内部アルゴリズムがあるとは言えませんEXCEPT
。の場合A EXCEPT B
、エンジンはAから個別の(必要な場合)タプルを取得し、Bで一致する行を減算します。特別なクエリプラン演算子はありません。区別と減算は、ソートまたは結合で表示される一般的な演算子を介して実装されます。ネストされたループ結合、マージ結合、およびハッシュ結合がすべてサポートされています。これを示すために、1組のヒープに1500万行をスローします。
DROP TABLE IF EXISTS dbo.TABLE_1;
CREATE TABLE dbo.TABLE_1 (
COL1 BIGINT NULL,
COL2 BIGINT NULL
);
INSERT INTO dbo.TABLE_1 WITH (TABLOCK)
SELECT TOP (15000000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), NULL
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
OPTION (MAXDOP 1);
DROP TABLE IF EXISTS dbo.TABLE_2;
CREATE TABLE dbo.TABLE_2 (
COL1 BIGINT NULL,
COL2 BIGINT NULL
);
INSERT INTO dbo.TABLE_2 WITH (TABLOCK)
SELECT TOP (15000000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), NULL
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
OPTION (MAXDOP 1);
オプティマイザは、ソートと結合の実装方法について通常のコストベースの決定を行います。2つのヒープを使用すると、期待どおりにハッシュ結合が得られます。インデックスを追加するか、いずれかのテーブルのデータを変更することで、他の結合タイプを自然に確認できます。以下では、説明のために、ヒントを使用してマージ結合とループ結合を強制しています。
内部的に各行のハッシュを取得して比較しますか?
いいえ。他の結合と同様に実装されます。1つの違いは、NULLは等しいものとして扱われることです。これは、実行プランで確認できる特別なタイプの比較です<Compare CompareOp="IS">
。ただし、EXCEPT
キーワードを含まないT-SQLで同じプランを取得できます。たとえば、次のクエリプランEXCEPT
は、ハッシュ結合を使用するクエリとまったく同じです。
SELECT t1.*
FROM
(
SELECT DISTINCT COL1, COL2
FROM dbo.TABLE_1
) t1
WHERE NOT EXISTS (
SELECT 1
FROM dbo.TABLE_2 t2
WHERE (t1.COL1 = t2.COL1 OR (t1.COL1 IS NULL AND t2.COL1 IS NULL))
AND (t1.COL2 = t2.COL2 OR (t1.COL2 IS NULL AND t2.COL2 IS NULL))
);
実行プランのXMLを比較しても、エイリアスなどの表面的な違いのみが明らかになります。ハッシュ結合のプローブ残差は行の比較を行います。どちらのクエリでも同じです。
それでも疑問がある場合は、使用可能な最高のサンプルレートでPerfViewを実行して、クエリのあるコールスタックEXCEPT
とないクエリのコールスタックを取得しました。結果を並べて次に示します。
本当の違いはありません。プラン内のハッシュが一致するため、参照ハッシュが存在する呼び出しスタックが存在します。自然なマージ結合を取得するためにインデックスを追加すると、呼び出しスタックにハッシュへの参照が表示されなくなります。
発生するハッシュは、ハッシュ一致演算子の実装によるものです。EXCEPT
特別な内部ハッシュ比較につながる特別なものはありません。