章: 第5章: 設計品質を上げる
ログテーブルが数千万件を超えたとき、どう対処しますか?
アクセスログや履歴データを1つのテーブルに蓄積し続けると、削除クエリが重くなり、バックアップに時間がかかり、インデックスが肥大化する問題が起きます。DELETE WHERE accessed_at < '2024-01-01' を流すだけで数十分かかる、というケースも珍しくありません。
MySQLのパーティションを活用すると、月ごと・年ごとにデータを物理的に分割でき、期間削除を ALTER TABLE ... DROP PARTITION の一瞬で完了させることができます。
パーティションの種類と使いどころ
| パーティション種別 | 分割キー | 向いているケース |
| RANGE | 値の範囲(日付・IDなど) | 月次ログ・期間削除が必要なデータ |
| LIST | 指定した値のリスト | 地域コード・カテゴリなど固定値での分割 |
| HASH | ハッシュ値で均等分散 | 均等なI/O分散が目的の場合 |
| KEY | MySQL内部キーで均等分散 | 主キーによる均等分割 |
実務での第一候補は RANGE パーティション(日付キー) です。期間削除と検索の両方に効果があります。
チェックポイント: パーティションは「全テーブルに適用すべき万能手段」ではありません。WHERE句にパーティションキーが含まれない検索では全パーティションを走査するため、むしろ遅くなることがあります。適用前に
EXPLAIN PARTITIONSで動作を確認してください。
実際のコードサンプル
CREATE TABLE access_logs (
id BIGINT UNSIGNED NOT NULL,
accessed_at DATETIME NOT NULL,
user_id BIGINT UNSIGNED,
PRIMARY KEY (id, accessed_at)
)
PARTITION BY RANGE (TO_DAYS(accessed_at)) (
PARTITION p202604 VALUES LESS THAN (TO_DAYS('2026-05-01')),
PARTITION p202605 VALUES LESS THAN (TO_DAYS('2026-06-01'))
);
まとめ & 次のステップ
- パーティションは「期間削除が頻繁」「検索範囲が明確」なテーブルに限定して検討する
- まずは月次ログなど適用条件が明確なテーブルから始める
DROP PARTITIONによる高速削除はパーティションの最大のメリットなので積極的に活用する- WHERE句にパーティションキーを含めないと効果がないため、クエリパターンを先に確認する
- 既存テーブルへの後付けは
ALTER TABLE ... PARTITION BYで可能だが、大量データの場合はロック時間に注意する
次回は ビューとストアドプロシージャ を学びます。共通SQLをDB側で管理する方法と、その使い分けの判断基準を解説します。