8

2 つの比較的単純なテーブルを結合しようとしていますが、クエリで深刻なハングアップが発生しています。理由はわかりませんが、「between」機能と関係があるのではないかと思います。私の最初のテーブルは次のようになります(他の多くの列がありますが、これは私が引っ張っている唯一の列です):


RowNumber
1
2
3
4
5
6
7
8

2 番目のテーブルは、行を「ブロック」に「グループ化」し、次のスキーマを持ちます。


BlockID     RowNumberStart     RowNumberStop
1           1                  3
2           4                  7
3           8                  8

私が取得しようとしている望ましい結果は、最初のテーブルと同じ行数で、以下のように RowNumber を BlockID にリンクすることです。したがって、結果は次のようになります。


RowNumber   BlockID           
1           1
2           1
3           1
4           2
5           2
6           2
7           2 
8           3

それを取得するために、次のクエリを使用して、結果を一時テーブルに書き込みました。


select A.RowNumber, B.BlockID
into   TEMP_TABLE
from   TABLE_1 A left join TABLE_2 B
on     A.RowNumber between B.RowNumberStart and B.RowNumberStop

TABLE_1 と TABLE_2 は、実際には非常に大きなテーブルです。テーブル 1 は約 122M 行で、TABLE_2 は約 65M 行です。TABLE_1 では、RowNumber は「bigint」として定義され、TABLE_2 では、BlockID、RowNumberStart、および RowNumberStop はすべて「int」として定義されます。それが違いを生むかどうかはわかりませんが、その情報も含めたかっただけです。

クエリは 8 時間ハングアップしています。このタイプと量のデータに対する同様のクエリは、これほど長い時間はかかりません。したがって、このクエリをハングアップさせているのは「before」ステートメントである可能性があるのではないかと考えています。

これをより効率的にする方法についての提案を歓迎します。

4

2 に答える 2

9

BETWEEN は単に次の省略形です。

select A.RowNumber, B.BlockID
into   TEMP_TABLE
from   TABLE_1 A left join TABLE_2 B
on     A.RowNumber >= B.RowNumberStart AND A.RowNumber <= B.RowNumberStop

実行計画が B から A に移動する場合 (ただし、左結合は、実際には A から B に移動する必要があることを示します)、TABLE_1 が RowNumber でインデックス付けされていると想定しています (これは、このクエリをカバーする必要があります)。RowNumber にのみクラスター化インデックスがあり、テーブルが非常に広い場合は、RowNumber にのみ非クラスター化インデックスを使用することをお勧めします。

それ以外の場合は、RowNumberStart DESC または RowNumberStop ASC で TABLE_2 にインデックスを付ける必要があります。特定の A では、RowNumberStart で DESC が一致する必要があるためです。

結合基準が設定されている方法で、結合を INNER JOIN に変更することをお勧めします。(ブロックなしで TABLE_1 を取得する予定はありますか?)

実行計画を見ると、パフォーマンスが悪い理由についてより多くの手がかりが得られるはずですが、TABLE_1 へのシークで Stop 基準が使用されていない可能性があります。

残念ながら、 に関する SQLMenace の回答SELECT INTOは削除されました。それに関する私のコメントは、@MartinSELECT INTOのパフォーマンスは以前ほど悪くはありませんが、型とNULL可能性を推測するCREATE TABLEため、ほとんどのプロダクションにはまだお勧めです。SELECT INTOこれは、実行していると思われることを確認する場合は問題ありませんが、超長いvarcharまたはdecimal非常に奇妙な精度の列を使用すると、テーブルが奇数になるだけでなく、パフォーマンスの問題が発生する可能性があります (特に、LEFT などを忘れた場合の大きな varchar の一部で)。テーブルがどのように見えるかを明確にするのに役立つと思います。多くの場合、WHERE 0 = 1 を使用して SELECT INTO を実行し、スキーマをチェックアウトしてから、微調整を加えてスクリプトを作成します (IDENTITY の追加やタイムスタンプの既定値を持つ列の追加など)。

于 2011-04-07T14:28:41.873 に答える
1

主な問題が 1 つあります。一度に大量のデータを表示したい場合です。テーブル 1 の 1 億 2,200 万行すべての結果を一度に処理したいですか? 本当にそれが必要ですか?

于 2011-04-07T14:24:14.033 に答える