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


10

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

David Lozinksiは、SQLの調査を実行しました。新しいレコードが存在しない場合に、新しいレコードを挿入する最も速い方法です。以下の結果に密接に関連しています。

前提: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のテスト結果に近いマップ

ここに画像の説明を入力してください


回答:


10

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特別な内部ハッシュ比較につながる特別なものはありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.