2

小さなテーブル (〜 400 行) と大きなテーブル (〜 1500 万行) の 2 つのテーブルがあり、大きなテーブルに関連付けられたエントリを持たない小さなテーブルからレコードを見つけようとしています。

クエリで大きなパフォーマンスの問題が発生しています。

クエリは次のとおりです。

SELECT * FROM small_table WHERE NOT EXISTS
  (SELECT NULL FROM large_table WHERE large_table.small_id = small_table.id)

列は、プライマリ キーであるlarge_table.small_idsmall_table のidフィールドを参照します。クエリ プランは、外部キー インデックスが large_table に使用されていることを示しています。

PLAN (large_table (RDB$FOREIGN70))
PLAN (small_table NATURAL)

両方のテーブルのインデックスの統計が再計算されました。

クエリの実行には数時間かかります。これは期待されていますか?

  • もしそうなら、より速くなるようにクエリを書き直すことはできますか?
  • そうでない場合、何が間違っている可能性がありますか?
4

2 に答える 2

1

大きなテーブルに small_id の個別の値が比較的少ない場合は、次のようにするとパフォーマンスが向上する可能性があります。

select *
from small_table st left outer join
     (select distinct small_id
      from large_table
     ) lt
     on lt.small_id = st.id
where lt.small_id is null

この場合、大きなテーブルのフル スキャンを実行してから小さなテーブルのインデックス ルックアップを実行すると、パフォーマンスが向上します。これは、実行していることとは逆です。個別を実行すると、大きなテーブルでインデックス スキャンが実行され、小さなテーブルの主キー インデックスが使用されます。

于 2012-06-27T21:26:25.330 に答える
1

Firebird についてはよくわかりませんが、他の DB では多くの場合、結合の方が高速です。

SELECT    *
FROM      small_table st
LEFT JOIN large_table lt
ON        st.id = lt.small_id
WHERE     lt.small_id IS NULL

試してみませんか?

もう 1 つのオプションは、本当に行き詰まっていて、これを実行する必要がある状況に応じて、small_id 列を large_table から取り出して一時テーブルに入れ、左結合 / EXISTS クエリを実行することです。

于 2012-06-27T18:40:41.440 に答える