ビットマップフィルターを使用したクエリプランは、読みにくい場合があります。以下からの再分割ストリームのBOLの記事(強調鉱山):
Repartition Streamsオペレーターは、複数のストリームを消費し、レコードの複数のストリームを生成します。レコードの内容と形式は変更されません。クエリオプティマイザーがビットマップフィルターを使用する場合、出力ストリームの行数が削減されます。
さらに、ビットマップフィルターに関する記事も役立ちます。
ビットマップフィルタリングを含む実行プランを分析する場合、データがプランをどのように流れ、フィルタリングが適用されるかを理解することが重要です。ビットマップフィルターと最適化されたビットマップは、ハッシュ結合のビルド入力(ディメンションテーブル)側に作成されます。ただし、実際のフィルタリングは通常、ハッシュ結合のプローブ入力(ファクトテーブル)側にある並列処理演算子内で実行されます。ただし、ビットマップフィルターが整数列に基づいている場合、フィルターは並列処理演算子ではなく、初期テーブルまたはインデックススキャン操作に直接適用できます。この手法は、行内最適化と呼ばれます。
私はそれがあなたのクエリで観察していることだと信じています。ビットマップ演算子がIN_ROW
ファクトテーブルに反している場合でも、再パーティションストリーム演算子がカーディナリティの推定値を削減することを示す比較的単純なデモを思いつくことができます。データ準備:
create table outer_tbl (ID BIGINT NOT NULL);
INSERT INTO outer_tbl WITH (TABLOCK)
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values;
create table inner_tbl_1 (ID BIGINT NULL);
create table inner_tbl_2 (ID BIGINT NULL);
INSERT INTO inner_tbl_1 WITH (TABLOCK)
SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
INSERT INTO inner_tbl_2 WITH (TABLOCK)
SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
実行すべきではないクエリを次に示します。
SELECT *
FROM outer_tbl o
INNER JOIN inner_tbl_1 i ON o.ID = i.ID
INNER JOIN inner_tbl_2 i2 ON o.ID = i2.ID
OPTION (HASH JOIN, QUERYTRACEON 9481, QUERYTRACEON 8649);
計画をアップロードしました。近くのオペレーターを見てくださいinner_tbl_2
:
また、Paul WhiteによるNullable Columnsのハッシュ結合の 2番目のテストが役立つ場合があります。
行削減の適用方法にはいくつかの矛盾があります。少なくとも3つのテーブルがある計画でしか見ることができませんでした。ただし、適切なデータ分散を使用すると、予想される行の削減は合理的と思われます。ファクトテーブルの結合された列に、ディメンションテーブルに存在しない繰り返し値が多数あるとします。ビットマップフィルターは、結合に到達する前にそれらの行を削除する場合があります。クエリの場合、推定値は1までずっと削減されます。ハッシュ関数間で行がどのように分散されるかが良いヒントになります。
それに基づいて、Object1.Column21
列に繰り返し値がたくさんあると思われます。繰り返し列がたまたま統計のヒストグラムにない場合Object4.Column19
SQL Serverはカーディナリティの推定値を非常に間違っている可能性があります。
クエリのパフォーマンスを改善できる可能性があるので、心配する必要があると思います。もちろん、クエリが応答時間またはSLA要件を満たしている場合は、さらに調査する価値はありません。ただし、さらに調査したい場合は、(統計の更新以外に)クエリオプティマイザーがより良い情報を持っている場合に、より良い計画を選択するかどうかを知るためにできることがいくつかあります。あなたは結果が間の結合入れることができますDatabase1.Schema1.Object10
し、Database1.Schema1.Object11
一時テーブルに、あなたは、ネストされたループ結合を取得し続けるかどうかを確認します。LEFT OUTER JOIN
クエリオプティマイザーがそのステップで行数を削減しないように、その結合を変更できます。MAXDOP 1
クエリにヒントを追加して、何が起こるかを確認できます。使用できますTOP
派生テーブルを使用して、結合を最後に強制するか、クエリから結合をコメントアウトすることもできます。うまくいけば、これらの提案はあなたが始めるのに十分です。
質問の接続項目に関して、それがあなたの質問に関連していることはほとんどありません。その問題は、貧弱な行の見積もりとは関係ありません。これは、バックグラウンドでクエリプランで処理される行が多すぎる原因となる並列処理の競合状態に関係しています。ここでは、クエリが余分な作業を行っていないようです。