2016-12-03 10 views
3

人のレコード(〜400万)をループし、複数の更新(〜100)と単一のdelete文(これらの更新と削除はすべて異なる表にあります)を実行するPL/SQLスクリプトがあります。私が直面している問題は、1つのdeleteステートメントが実行時間の半分を単独で消費するということです。私はdelete文を実行するとインデックスを更新する必要があるが、それはむしろばかげていることを理解している。現在、このスクリプトをdbms_parallel_executeを使用して1つのスレッドでテストしていますが、このスクリプトをマルチスレッドする予定です。複数の小さな削除

DELETE FROM table1 t1 
WHERE (t1.key1, t1.key2) IN (SELECT t2.key1, t2.key2 
           FROM table2 t2 
           WHERE t2.parm1 = 1234 
           AND t2.parm2 = 5678). 

次の事実:私は次のようなクエリを実行しています

  • 表2(約30万レコード)は〜10倍TABLE1より大きい(約3万件のレコード)であります。
  • TABLE1の主キー(KEY1、KEY2)
  • は、私が無効になってい
  • 表2(PARM1、PARM2)上のインデックスがあり
  • 表2(KEY1、KEY2)の主キーがありますがありますテーブル2(key1、key2)を参照するtable1(key1、key2)の外部キー制約
  • table1には他の制約はありませんが、table2の制約が増えます。 TABLE1に

  • すべてのトリガーを無効

  • ていたこのクエリの実行計画は、私の更新ステートメントの多くよりも低コストでアップします(私はこれはあまりを考慮していません知っています)。

EXPLAIN PLAN出力:

OPERATION       OPTIONS                        OBJECT_INSTANCE        OBJECT_TYPE       OPTIMIZER                       SEARCH_COLUMNS        ID           PARENT_ID         DEPTH          POSITION          COST           CARDINALITY         BYTES          CPU_COST          IO_COST          TIME           
------------------------------------ ---------------------------------------------------------------------------------------------------- -------------------------------------------- ------------------------------------ ---------------------------------------------------------------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- -------------------------------------------- 
DELETE STATEMENT                                                   ALL_ROWS                                              0                       0           5           5           1           36          38043           5           1 
DELETE                                                                                                     1           0           1           1                                                                    
NESTED LOOPS                                                                                                    2           1           2           1           5           1           36          38043           5           1 
TABLE ACCESS       BY INDEX ROWID                                 2 TABLE        ANALYZED                                              3           2           3           1           4           1           25          29022           4           1 
INDEX        RANGE SCAN                                  INDEX        ANALYZED                                  1           4           3           4           1           3           1                      21564           3           1 
INDEX        UNIQUE SCAN                                  INDEX (UNIQUE)      ANALYZED                                  2           5           2           3           2           1           1           11           9021           1           1 

これはより速く行く削除作るためにどのような方法があった場合、私は思っていました。私はbulk deleteを実行しようとしましたが、実行時間を改善するようには見えませんでした。すべての削除を実行してからインデックスを更新する方法があれば、より速く実行されると思われます。私はレコードを(と複数の条件を実行している)別のテーブルから削除を実行するループしているので、明らかにselectからcreateテーブルを行うことは、画像の外です。

+0

あなたのテーブルは何時からインデックス構成されていますか? TABLE_NAME = 'MYTABLENAME'をALL_TABLES WHEREからSELECT IOT_TYPEを試してみてください。結果がNULLでない場合は、索引構成されています。 –

+0

結果は両方のテーブルでNULLです。 – Mocking

+1

説明出力から書式を保持してください。インデントを分析することは重要です。 –

答えて

0

30mレコードのテーブル2のクエリを実行すると、パフォーマンスが低下し、ロックの問題が発生し、クエリの速度が低下する可能性があります。

table2からデータを選択しているインラインクエリを移動することをお勧めします。表2は、削除を駆動していて、候補レコードを削除する必要があります。カーソルとして実行したり、このデータをテンポラリテーブルに配置したりすることができます。 500、1000のチャンクでdeleteを実行してからコミットします。このチャンクは、結果に基づいて最適化することができます。削除時の

インデックスの更新は、このプロセスは、非就業時間中に実行されている場合、あなたは、インデックスを無効にして再度作成し直して、冗長ではない..です

0

外側のクエリが「小さい」と内側のクエリである場合、私はそう思います「大きい」 - 存在する場所は非常に効率的です。

In節の代わりにwhere節が存在するかどうか試してから、explainプランとパフォーマンスを確認してください。

DELETE FROM table1 t1 
WHERE 
Exists (select 1 
    FROM table2 t2 
    WHERE t2.parm1 = 1234 
AND t2.parm2 = 5678 
AND t2.key1 = t1.key1 
AND t2.key2 = t1.key2 
) 
関連する問題