web-dev-qa-db-ja.com

EXCEPT演算子の背後にあるアルゴリズムは何ですか?

Except 演算子がSQL Serverの内部で機能する方法の内部アルゴリズムは何ですか?内部的に各行のハッシュを取得して比較しますか?

David Lozinksiは調査を行いました SQL:まだ存在しない新しいレコードを挿入する最速の方法 彼は、Exceptステートメントが多数の行に対して最速であることを示しました。以下の結果に密接に関連しています。

前提:1列のみを比較するため、左結合が最も高速であると思いますが、すべての列を比較する必要があるため、例外として最も時間がかかります。
これらの結果を踏まえて、私たちの考えは次のとおりです。例外として、自動的かつ内部的に各行のハッシュを取得しますか?私は実行計画を除いて見て、それはいくつかのハッシュを利用しています。

背景:私たちのチームは2つのヒープテーブルを比較していました。テーブルAテーブルBにない行がテーブルBに挿入されました。

(レガシーテキストファイルシステムの)ヒープテーブルには、主キー/ GUID /識別子がありません。一部のテーブルには重複行があったため、各行のハッシュを見つけ、重複を削除して、主キー識別子を作成しました。

1)最初に、(ハッシュ列)を除いて、exceptステートメントを実行しました

select * from TableA
Except
Select * from TableB,

2)次に、HashRowIdの2つのテーブル間で左結合比較を実行しました

select * 
FROM dbo.TableA A
left join dbo.TableB B
    on A.RowHash =  B.RowHash
where B.Hash is null

驚いたことに、Except Statement Insertが最速でした。

結果は実際にDavid Lozinksiからのテスト結果に近いマップ

enter image description here

10
user162241

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つのヒープを使用すると、期待どおりにハッシュ結合が得られます。インデックスを追加するか、いずれかのテーブルのデータを変更することで、他の結合タイプを自然に確認できます。以下では、説明のために、ヒントを使用してマージ結合とループ結合を強制しています。

joins

内部的に各行のハッシュを取得して比較しますか?

いいえ。他の結合と同様に実装されます。 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を比較しても、エイリアスなどの表面的な違いのみが明らかになります。ハッシュ結合のプローブ残差は、行の比較を行います。これらは両方のクエリで同じです。

enter image description here

それでも疑問がある場合は、EXCEPTを使用したクエリとそれを使用しないクエリのコールスタックを取得するために、利用可能な最高のサンプルレートで PerfView を実行しました。結果を並べて次に示します。

enter image description here

本当の違いはありません。プラン内のハッシュが一致するため、参照ハッシュが存在する呼び出しスタックが存在します。自然なマージ結合を取得するためにインデックスを追加すると、呼び出しスタックにハッシュへの参照が表示されなくなります。

enter image description here

発生するハッシュは、ハッシュ一致演算子の実装によるものです。特別な内部ハッシュ比較につながるEXCEPTについて特別なことは何もありません。

10
Joe Obbish