0

ref_table_id、ref_objid の 2 つの列を持つテーブルがあります。このテーブルは、他のテーブルのオブジェクトを参照するために使用されます。実際には 2 つ以上の列がありますが、他の列は重要ではありません。

次のクエリの実行には 1 秒かかります。

delete from ref_table_id
where (ref_table_id = 1 and 
       ref_objid not in (select objid from table1))

同様に、このクエリの実行には 1 秒かかります。

delete from ref_table_id
where (ref_table_id = 2 and 
       ref_objid not in (select objid from table2))

ただし、このクエリの実行には 3 分かかります。

delete from ref_table_id
where (ref_table_id = 1 and 
       ref_objid not in (select objid from table1))
   or (ref_table_id = 2 and 
       ref_objid not in (select objid from table2))

最後のクエリに時間がかかるのはなぜですか? 基本的には、最初の 2 つの組み合わせです。誰でもこれを説明できますか?

オラクルを使用しています。

ありがとうございました

4

2 に答える 2

1

orOracle は、 inwhere句を使用すると非常に遅いことで有名です。その理由は、これらの条件ではインデックスも使用できないためです。

この場合、 2 つの別個のdeleteステートメントを実行することをお勧めします。

どうしても 1 つのステートメントで実行したい場合は、次のようにしてみてください。

delete from ref_table_id
where
  id in 
    ( select id from ref_table_id
      where
        ref_table_id = 1 and 
        ref_objid not in (select objid from table1)
      union all
      select id from ref_table_id
      where
        ref_table_id = 2 and 
        ref_objid not in (select objid from table2) 
    )

union all非常に高速で、 を使用する必要がありませんor。しかし一方で、それはステートメントをより複雑にするので、私が言ったように、単に 2 つの削除を実行する方がはるかに簡単かもしれません。

于 2013-07-04T13:26:32.310 に答える
0

オラクルのクエリに時間がかかる理由はたくさんありますが、この場合は次のように推測できます。

1- 内部選択 (table1 から objid を選択し、table2 から objid を選択) を各行で評価する必要があります。

2- 統計が古いため、オラクルは不適切な実行計画を作成しています。新しい統計を収集してみてください。

3-結合に含まれる列のインデックスを作成してみてください。

于 2013-07-04T12:51:32.737 に答える