ユニオンビューをより効率的に実行するにはどうすればよいですか?


8

私はパフォーマンスの理由でアクティブテーブルとアーカイブテーブルに分割し、直接フィールドマッピングを使用して、アーカイブプロセスを毎晩実行する大きなテーブル(数千から数億レコード)を持っています。

コード内のいくつかの場所で、アクティブテーブルとアーカイブテーブルを結合するクエリを実行する必要があります。ほぼ常に1つ以上のフィールド(両方のテーブルにインデックスを配置している)によってフィルター処理されます。便宜上、次のようなビューがあると理にかなっています。

create view vMyTable_Combined as
select * from MyTable_Active
union all
select * from MyTable_Archive

しかし、次のようなクエリを実行すると

select * from vMyTable_Combined where IndexedField = @val

でフィルタリングする前に、ActiveとStoreのすべてに対して結合を行う@valため、パフォーマンスが低下します。

ユニオン@valを作成する前に、ユニオンビューの2つのサブクエリを各フィルターで作成する賢い方法はありますか?

それとも、私が目指していることを達成するために提案する他のアプローチがあるかもしれません。つまり、インデックス付きフィールドによってフィルター処理されたユニオンレコードセットを取得する簡単で効率的な方法ですか。

編集:ここに実行計画があります(そして実際のテーブル名がここに表示されます):

実行計画

奇妙なことに、アクティブテーブルは実際には正しいインデックス(およびRID検索?)を使用していますが、アーカイブテーブルはテーブルスキャンを実行しています!


コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
ポールホワイト9

回答:


8

質問へのコメントは、問題がOPがクエリの開発に使用していたテストデータベースが、運用データベースとは根本的に異なるデータ特性を持っていることを示しています。行数がはるかに少なく、フィルタリングに使用されているフィールドの選択性が不十分でした。

列内の個別値の数が少なすぎる場合、インデックスは十分に選択的ではない可能性があります。この場合、シーケンシャルテーブルスキャンは、インデックスシーク/行ルックアップ操作よりも安価です。通常、テーブルスキャンはシーケンシャルI / Oを多用します。これは、ランダムアクセス読み取りよりもはるかに高速です。

多くの場合、クエリが行の数パーセント以上を返す場合、ランダムI / Oを多用するインデックスシーク/行ルックアップまたは同様の操作よりもテーブルスキャンを実行する方が安価です。


1

追加するために、私が見つけたもの。もしあなたがそうするなら:

create view vMyTable_Combined as
select *, 1 AS [Active] from MyTable_Active
union all
select *, 0 AS [Active] from MyTable_Archive

次に、[アクティブ]フィールドでフィルタリングし、他のパーツが読み込まれていないことを確認します。

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