0

delete私はオラクルで次のクエリを持っています。一度に約 1000 レコードがデータベースから削除されます。

クエリで「in」を使用しました。このクエリを記述するより良い方法はありますか?

DELETE FROM BI_EMPLOYEE_ACTIVITY      
WHERE EMPLOYEE_ID in (    
    SELECT    
      EMP_ID   
    FROM   
      BI_EMPLOYEE   
    WHERE   
      PRODUCT_ID = IN_PRODUCT_ID  
  );
4

6 に答える 6

0

データ分布の説明がないため、この質問に答えることは実際には不可能です: 各テーブルには何行ありますか? テーブル間の関係は何ですか?削除の影響を受ける行数は?

両方のテーブルが大きく (これは最適化の問題であるため) 、親子 1..N の関係があると仮定BI_EMPLOYEEします。BI_EMPLOYEE_ACTIVITY

削除の影響を受ける行がほとんどない場合、これは同じ従業員が多くなくPRODUCT_ID、各従業員の活動が少ないことを意味します。この場合、 と の両方にインデックスを付けるのが理にかなっていBI_EMPLOYEE (product_id)ますBI_EMPLOYEE_ACTIVITY (employee_id)

これはおそらくそうではありませんが、削除はおそらく多くの行に影響します。その場合、インデックスが邪魔になる可能性があります。削除が多くの行に影響する場合、最速のアクセス パスはおそらくFULL TABLE SCAN + HASH JOIN.

ここでいくつかのメトリクスが必要です: 削除された行数は? それはどのくらいかかりますか?これは、大規模な DML は常に時間がかかるためです。特にDELETE、大量の UNDO が生成されるためです。

asktomの「Deleting many rows from a big table」DELETEで説明されているように、大きな に代わるものがあります。

  1. 削除された行なしでテーブルを再作成します
  2. データを分割し、並列削除を行う
  3. パーティションを削除することによって削除が行われるように、データを分割します
于 2012-09-05T08:29:18.747 に答える
0

IN の代わりにEXISTを試すこともできます:

DELETE FROM BI_EMPLOYEE_ACTIVITY      
WHERE EXISTS (    
    SELECT    
      EMP_ID   
    FROM   
      BI_EMPLOYEE   
    WHERE   
      PRODUCT_ID = IN_PRODUCT_ID 
    AND
      EMP_ID =  EMPLOYEE_ID
  );
于 2012-09-05T05:37:20.283 に答える
0

EMP_ID にインデックスを配置すると役立つ場合があります。他の最適化が可能であるとは思いません。クエリは非常に単純で簡単です

于 2012-09-05T05:30:33.903 に答える
0

BI_EMPLOYEEこの順序で列のテーブルにインデックスを作成しますPRODUCT_ID, EMP_ID(最初に product_id)。

BI_EMPLOYEE_ACTIVITYそして、列のテーブルにインデックスを作成しますEMPLOYEE_ID

于 2012-09-05T08:02:21.117 に答える
0

クエリのインデックスを作成する以外に、テーブルが非常に大きくなったときにロックの問題を確認する必要があることを追加します。可能であれば、排他モードでテーブルをロックしてみてください。データベースからロックし、それが不可能な場合は、2500 レコードごとに削除をコミットしてみてください。行のロックに固執している場合でも、データベースのロックが枯渇することはありません。

于 2012-09-10T21:26:42.507 に答える
0

PRODUCT_ID 列にインデックスを作成します。これにより、検索が高速化されます。列が varchar 型の場合、値を大文字または小文字に変換する場合は関数 index を使用します

于 2012-09-05T05:36:11.350 に答える