数千万行の一括削除は、高負荷のデータベースでは典型的かつ非常に危険な操作の一つです。歴史的に、多くの人々は単に DELETE FROM を実行し、それがテーブルのロックやトランザクションログのオーバーフローを引き起こしました。主な問題は、トランザクションが非常に大きくなり、管理プロセスが遅延し、ロールバックの結果が予測できなくなることです。
解決策 — 小さなトランザクションで小さな行数をループ処理して、一括削除を "バッチ" 処理することで、ロックとシステムへの影響を最小限に抑えます。
コードの例(SQL Server):
WHILE 1=1 BEGIN DELETE TOP (10000) FROM YourHugeTable WHERE CreatedAt < DATEADD(year,-2,GETDATE()); IF @@ROWCOUNT = 0 BREAK; WAITFOR DELAY '00:00:01'; -- 負荷を減らすための小休止 END
主な特徴:
DELETEの代わりにTRUNCATEを実行すると、常に速くて安全ですか?
いいえ。TRUNCATE は格段に速いですが:
大量のDELETEでフィルター列のインデックスを使用することは重要ですか?
はい、フィルター列(たとえば、CreatedAt)に適切なインデックスがあれば、削除対象行の検索が速くなり、テーブルへの負荷が軽減されます。インデックスが無い場合、リクエストはテーブル全体に影響を及ぼします。
CREATE INDEX idx_createdat ON YourHugeTable(CreatedAt);
複数のスレッドで同時に大量のDELETEを実行するとどうなりますか?
ロックについての競争が発生します:ロックのエスカレーション、待機時間の増加、デッドロックの可能性があります。同じテーブルからの大量削除は、一つのプロセスで行われるべきで、非常に注意深く範囲を分ける必要があります。
DBAが60百万行のテーブルを単一の DELETE FROM Log WHERE dt < '2021-01-01' クエリでクリアしようとしました。サーバーはほぼ "フリーズ" し、他のプロセスは実行を待機し、ログファイルが急増し、リカバリが長引きました。
利点:
欠点:
削除を10,000行ずつのバッチに分け、プロセスを制御し、各バッチの後に小休止しました。サーバーは安定して動作し、他のタスクも実行され、管理者が進捗を監視しました。
利点:
欠点: