MySQL を運用するなら、以下は明らかにしておく必要があります。
DELETEしたらディスク容量は減るのか?
DROPしたらどうなるのか?
実際に試してみました。
テスト環境
- 東京リージョン
- RDS for MySQL
- ストレージタイプ:gp系(一般的な構成)
- 監視メトリック:FreeStorageSpace
DELETEしてみた
150万レコードのテーブルから 75万レコードを DELETE してみます。
監視メトリック:FreeStorageSpace
| 時間 | FreeStorageSpace |
|---|---|
| DELETE前 | 15,205,109,760 bytes |
| 2分後 | 15,205,109,760 bytes |
| 4分後 | 15,154,778,112 bytes |
| 6分後 | 15,154,778,112 bytes |
| 8分後 | 15,138,000,896 bytes |
結論:ほとんど減らない
多少揺れはあるものの、削除したレコード分の容量が戻ったとは言えません。
DROPしてみた
150万レコードのテーブルを丸ごと DROP してみます。
監視メトリック:FreeStorageSpace
| 時間 | FreeStorageSpace |
|---|---|
| DROP前 | 15,138,000,896 bytes |
| 1分後 | 17,424,207,872 bytes |
| 以後 | 変化なし |
結論:明確に増えた(= ストレージが解放された)
約2GB以上の空き容量が戻りました。
理屈を調べてみた
DELETE ではストレージは減らない
DELETE はレコードを削除しますが、
- ページ内部に空き領域(フラグメント)が残る
- ファイルサイズは基本的に縮まらない
つまり:
「空き」はできるが、ディスクは返却されない
DROP TABLE ではストレージは解放される
テーブルを丸ごと削除すると、
- テーブルファイル自体が削除される
- OSにストレージが返却される
InnoDB の仕組み
一般的な MySQL(InnoDB)では、
mysql> SHOW VARIABLES LIKE 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
1 row in set (0.01 sec)
innodb_file_per_table = ON の場合
-
テーブルごとに
.ibdファイルが存在 -
DROP TABLE すると:
.ibdファイルが削除される- OSへストレージが返却される
今回の挙動はこれでした。
innodb_file_per_table = OFF の場合
-
共通 tablespace(ibdata1)を使用
-
DELETE や DROP しても
- ファイルサイズ自体は縮まらない
この場合はディスク容量は戻りません。
RDS for MySQL の場合
RDS も基本的には標準的な InnoDB と同じ挙動です。
- DROP TABLE で ibd ファイルは削除される
- FreeStorageSpace は増える
ただし:
- RDS は内部的にストレージを管理している
- 物理的な容量縮小と、メトリック反映にはタイムラグがある場合もある
補足事項 (要注意)
MySQL 8.0 Reference Manual File-Per-Table Tablespaces https://dev.mysql.com/doc/refman/8.0/en/innodb-file-per-table-tablespaces.html
File-Per-Table Tablespace Advantages の節に「テーブルをドロップするとストレージはOSに返される」とありますが、 File-Per-Table Tablespace Disadvantages の節には「テーブルドロップ時にはバッファプールがスキャンされる。スキャン時にはロックされる」とも書かれています。
サービスダウンを避けるためにはメンテナンス中に行ったほうが良さそうですね。
結論
| 操作 | ストレージは減る? |
|---|---|
| DELETE | 減らない |
| DROP TABLE | 減る(file-per-tableの場合) |