大量データを扱うシステムでは、
「DELETE文が異常に遅い」「1000件削除するだけで何分もかかる」
という現象は珍しくありません。
実際、筆者の環境でも
-
1500万件のテーブル
-
DELETE 1件 = 約1.2秒
-
DELETE 100件 = 約2分
-
DELETE 1000件 = 約20分
という、明らかに正常とは言えない状態に遭遇しました。
この記事では、
SQL(特にOracle)で DELETEが異常に遅くなる原因と対処法 を
現場目線でわかりやすくまとめます。
1. DELETEが遅い原因は「処理そのものが重い」から
SELECTは一瞬で返るのに、DELETEだけ異様に遅い。
これは DELETE内部の処理コストが非常に重い ためです。
DELETEが行うことは主に以下:
-
対象行の削除(表領域から除去)
-
インデックスから該当エントリの削除
-
Undoログの生成
-
Redoログの生成
-
ロック管理
-
トリガー処理(あれば)
このどれか、あるいは複数が詰まると
DELETEは1件ずつ遅くなり、数百件〜数千件だと“永遠に終わらない”状態になります。
2. DELETEが異常に遅いときの主な原因
2-1. インデックスの断片化・肥大化(最も多い)
大量INSERT / DELETE / UPDATE を繰り返したテーブルは
インデックスが “B-tree破損状態” になります。
症状:
-
DELETE 1件 = 1秒以上
-
100件DELETEでも数分
-
SELECTは速い(インデックス検索は生きている)
これはインデックス劣化の典型。
→ インデックス再構築で劇的に改善することがあります。
2-2. Undo / Redo の処理が追いつかない
大量DELETEを連続してキャンセルすると
-
Undoセグメント肥大
-
Redoログ切替待ち
-
I/Oスラッシング
-
Undo segment extension 待ち
などが発生し、DELETEが異常に遅くなります。
2-3. 外部キー参照(子テーブル)が存在する
DELETEのたびに
-
子テーブルを参照
-
存在チェック
-
参照整合性確認
を行うため、対象行が多いと極端に遅くなります。
※子テーブルを先に削除済なら影響なし。
2-4. トリガーが動いている
DELETEトリガーがあると
行ごとに処理が実行されるため、100行DELETEで100回 トリガーが動きます。
トリガー内でINSERT/UPDATEが走っていると、一気に重くなります。
2-5. テーブルやインデックスの断片化
特に1500万件級の大規模テーブルでは
断片化やI/O劣化によって DELETE が遅くなります。
2-6. ロックではない(SELECT が速ければ別原因)
「DELETEが遅い=ロック」と思われがちですが、
SELECTが瞬時に返るならロックではないことが多いです。
DELETE固有の処理が遅い証拠です。
3. DELETEが遅いときのチェックポイント(すぐ実行できる)
✔ ① SELECT COUNT は速い?
→ 速いならロックではない。
✔ ② 1件DELETEの時間を計測
→ 1秒以上かかるならインデックス劣化 or Undo詰まり。
✔ ③ インデックス数は多すぎない?
✔ ④ トリガーが無いか?
✔ ⑤ 子テーブルの外部キーは?
これだけでも原因の大半は特定できます。
4. 対策まとめ(実務で使える)
4-1. インデックス再構築(効果大)
DBA権限が必要ですが、再構築すると劇的に速くなります。
4-2. 統計情報の更新
4-3. 子テーブルを先に削除 or 一時的に外部キー無効化
4-4. トリガーの見直し / 一時無効化
4-5. DELETEを小分け(100件単位)で実行
大量DELETEは一度にやるのではなく
100件 or 1000件ごとに分割してCOMMITする方が安全。
※筆者環境では
100件DELETE = 約2分
1000件DELETE = 約20分
でした。
4-6. 一番速いのは「論理削除」
物理削除できないなら DELETE_FLG を立てる方法が最も安全。
これは DELETE より圧倒的に軽いです。
4-7. 本当に大量削除するなら「CTAS」が最強
残すデータだけ別テーブルにコピーして入れ替える方法。
DELETEより何倍も速いです。
5. まとめ
DELETEは単純なSQLに見えますが、
内部的には
-
インデックス更新
-
Undo/Redo 生成
-
ロック管理
-
外部キー参照
-
トリガー処理
など多くの処理が絡むため
大量データでは極端に遅くなることがあります。
特に大規模テーブル(1000万件以上)だと
1件 DELETE でも1秒以上かかることが普通にあります。
もし DELETE が遅くて固まる場合は、
-
SELECT が速いか確認
-
1件DELETEの時間を計測
-
インデックス・Undo/Redo・トリガーを疑う
-
小分けDELETE or 論理削除に切り替える
-
必要に応じてDBAにインデックス再構築を依頼
といったステップで原因を切り分けると
安全で確実に改善できます。
