MySQL テーブルデータのクリア (DELETE vs TRUNCATE)
DELETE 文と TRUNCATE TABLE 命令は、どちらもデータテーブルからデータを削除するために使用されますが、データベースエンジンにおける低レイヤーの処理が完全に異なります。その結果、パフォーマンス、ログの記録、および機能的な特性に顕著な差異が生じます。
1. DELETE 文:1行ずつの処理
DELETE は、DML(データ操作言語 / Data Manipulation Language)に分類されるコマンドです。DELETE 文を実行すると、たとえ対象がテーブル内の全行であっても、MySQL エンジンはそれを「一連の独立したシングル行操作」として扱います。
-- 特定の条件に一致する行を削除
DELETE FROM orders WHERE status = 'cancelled';
-- テーブル内のすべての行を削除
DELETE FROM orders;DELETE を実行すると、データベースエンジンはテーブルをスキャンし、設定した基準に一致するすべての行を特定します。その後、関連する制約(トリガー / Triggers や 外部キー / Foreign Keys など)をチェックし、レコードを1つずつ削除します。この処理が1行ごとに行われるため、MySQL はトランザクションログに各削除操作を記録します。
これが、DELETE がトランザクションをサポートしている理由です。InnoDB のようなストレージエンジン(Storage Engine)を使用している場合、誤って実行したことに気づけば、コミット(Commit)前にロールバック(Rollback)してデータを復旧させることができます。
しかし、この1行ずつ処理する方法はコンピューティングリソースの消費が非常に激しいです。数百万行のデータを含むテーブルで無条件の DELETE を実行すると、処理速度が非常に遅くなり、大量の CPU リソースを消費するだけでなく、トランザクションログのサイズが肥大化する原因となります。
2. TRUNCATE TABLE 命令:テーブルのリセット
TRUNCATE TABLE は、DDL(データ定義言語 / Data Definition Language)に分類されるコマンドです。これは行をスキャンして削除するのではなく、本質的に既存のテーブルを一度削除(Drop)し、同じ構造で再作成(Recreate)する仕組みで動作します。
TRUNCATE TABLE orders;テーブルを再作成するため、TRUNCATE は行ごとのスキャンを行いません。すべての行レベルの制約やトリガーを無視し、トランザクションログに個別のデータ削除を記録することもありません。これにより、テーブルにどれほど多くのレコードが含まれていても、実行速度はほぼ一瞬(インスタント)です。
最も重要なポイントは、テーブルに AUTO_INCREMENT(オートインクリメント)カラムが含まれている場合、TRUNCATE はそのカウンターを初期値(通常は 1)にリセットすることです。DELETE ではこのようなリセットは行われず、オートインクリメントのカウンターは削除前の位置から継続して増加します。
3. 機能の全面比較
| 特性 | DELETE | TRUNCATE TABLE |
|---|---|---|
| コマンドタイプ | DML (データ操作言語) | DDL (データ定義言語) |
| 実行パフォーマンス | 遅い (1行ずつ処理) | 極めて速い (直接削除して再構築) |
| WHERE 句 | サポート (細かなフィルタリングが可能) | 非サポート (全テーブルクリアのみ) |
| 自増カラム (Auto-Increment) | 現在のカウント値を維持 | 初期値にリセット |
| トランザクション対応 | ロールバック可能 (Rollback) | 通常は暗黙のコミット、ロールバック不可 |
| トリガー (Triggers) | DELETE トリガーが発火する | いかなるトリガーも発火しない |
判断基準のリファレンス:
- 特定の行をフィルタリングする必要がありますか? →
WHERE句を伴うDELETEを使用 - フィルタリングは不要で、オートインクリメント ID をリセットしたいですか? →
TRUNCATE TABLEを使用 - フィルタリングは不要で、ID はリセットしたくないが、データセットが非常に巨大ですか? →
TRUNCATE TABLEを推奨(速度面で有利)
4. 制約とセキュリティメカニズム
TRUNCATE は DDL コマンドであるため、MySQL におけるトランザクションの挙動が異なります。多くの設定において、TRUNCATE の実行は「暗黙のコミット(Implicit Commit)」を引き起こします。つまり、この操作をロールバックすることはできません。一度実行されると、データは即座に消失します。
さらに、現在のテーブルが別のテーブルから FOREIGN KEY(外部キー)制約によって参照されている場合、TRUNCATE は実行に失敗します。DELETE も参照整合性に違反する場合は失敗しますが、DELETE は WHERE 句を使用できるため、これらの関連関係を尊重しながら特定の行を削除するという「粒度(Granularity)」を持った操作が可能です。一方、TRUNCATE を実行するには、まず外部キーを削除するか無効化する必要があります。