Appearance
db2023 RANGE パーティショニング本番導入手順
Issue #2341 / 現役作業手順:
wp_db2023(接頭辞がwp_の場合)のDAYがdate型であることを確認したうえで、年別RANGEパーティションを追加する。大規模 ALTER のため、原則としてpt-online-schema-changeで実施する。
目的
db2023 は日別 raw の台単位データを保持する大きなテーブルで、最大 366 日の WHERE DAY IN (...) クエリでは対象期間に応じて大量行を読む。PARTITION BY RANGE (YEAR(DAY)) を導入し、MySQL の partition pruning で対象年のパーティションだけを読む状態にする。
前提
db2023.DAYはdate型であること。db2023にはDAYを含む一意制約または主キーがあること。現行の正本はUNIQUE KEY uk_day_dainum_hall (DAY, dainum, hall)。kishu_idバックフィルが本番で完了していること。- 実施直前に DB バックアップを取得し、アプリ側の該当画面で計測できる状態にしておくこと。
- 本番の WordPress テーブル接頭辞が
wp_でない場合は、以下のwp_db2023を実テーブル名に置き換えること。
事前確認
sql
SHOW CREATE TABLE `wp_db2023`;
SELECT COUNT(*) AS total,
SUM(`kishu_id` IS NULL) AS null_kishu_id,
MIN(`DAY`) AS min_day,
MAX(`DAY`) AS max_day
FROM `wp_db2023`;
SELECT `INDEX_NAME`, `COLUMN_NAME`, `NON_UNIQUE`, `SEQ_IN_INDEX`
FROM information_schema.STATISTICS
WHERE `TABLE_SCHEMA` = DATABASE()
AND `TABLE_NAME` = 'wp_db2023'
ORDER BY `INDEX_NAME`, `SEQ_IN_INDEX`;確認ポイント:
DAYがdate NOT NULLである。DAYを含む PRIMARY KEY または UNIQUE KEY がある。null_kishu_id = 0である。min_day/max_dayを見て、パーティション年を必要分だけ用意する。
DAY が varchar の場合は、この手順を止めて DAY の date 型統一を先に行う。STR_TO_DATE(DAY, ...) による式パーティションは pruning の確認が複雑になるため採用しない。
変更前計測
代表クエリの EXPLAIN PARTITIONS と実行時間を控える。日付は本番データの MAX(DAY) を基準に置き換える。
sql
SET profiling = 1;
EXPLAIN PARTITIONS
SELECT t.`DAY`, t.kishu, t.dainum, t.kaiten, t.samai, t.BB, t.RB, t.hall
FROM `wp_db2023` AS t
WHERE t.`DAY` IN ('2026-03-14', '2026-03-15', '2026-03-16')
ORDER BY t.dainum ASC, t.`DAY` ASC;
SELECT t.`DAY`, t.kishu, t.dainum, t.kaiten, t.samai, t.BB, t.RB, t.hall
FROM `wp_db2023` AS t
WHERE t.`DAY` IN ('2026-03-14', '2026-03-15', '2026-03-16')
ORDER BY t.dainum ASC, t.`DAY` ASC;
EXPLAIN PARTITIONS
SELECT t.`DAY`, t.hall, m.name AS kishu, SUM(t.samai) AS total_samai, COUNT(*) AS unit_count
FROM `wp_db2023` AS t
INNER JOIN `wp_db_kishu_master` AS m ON t.kishu_id = m.id
WHERE t.`DAY` BETWEEN '2025-03-17' AND '2026-03-16'
GROUP BY t.`DAY`, t.hall, m.name;
SELECT t.`DAY`, t.hall, m.name AS kishu, SUM(t.samai) AS total_samai, COUNT(*) AS unit_count
FROM `wp_db2023` AS t
INNER JOIN `wp_db_kishu_master` AS m ON t.kishu_id = m.id
WHERE t.`DAY` BETWEEN '2025-03-17' AND '2026-03-16'
GROUP BY t.`DAY`, t.hall, m.name;
SHOW PROFILES;
SET profiling = 0;推奨手順: pt-online-schema-change
Percona Toolkit が使える環境では、以下のようにオンライン DDL で実施する。--dry-run の成功を確認してから --execute に切り替える。
bash
pt-online-schema-change \
--alter "PARTITION BY RANGE (YEAR(\`DAY\`)) (
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026),
PARTITION p2026 VALUES LESS THAN (2027),
PARTITION p2027 VALUES LESS THAN (2028),
PARTITION p_future VALUES LESS THAN MAXVALUE
)" \
--alter-foreign-keys-method=auto \
--check-alter \
--check-plan \
--max-load Threads_running=50 \
--critical-load Threads_running=100 \
--chunk-time 0.5 \
--progress time,30 \
--dry-run \
D=DATABASE_NAME,t=wp_db2023--dry-run で問題がなければ、同じコマンドの --dry-run を --execute に置き換えて実行する。
代替手順: 直接 ALTER
十分なメンテナンス窓を確保できる場合のみ、直接 ALTER を検討する。実行中はテーブル再構築により負荷・ロックの影響が出る可能性がある。
sql
ALTER TABLE `wp_db2023`
PARTITION BY RANGE (YEAR(`DAY`)) (
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026),
PARTITION p2026 VALUES LESS THAN (2027),
PARTITION p2027 VALUES LESS THAN (2028),
PARTITION p_future VALUES LESS THAN MAXVALUE
);変更後確認
sql
SHOW CREATE TABLE `wp_db2023`;
SELECT `PARTITION_NAME`, `TABLE_ROWS`, `DATA_LENGTH`, `INDEX_LENGTH`
FROM information_schema.PARTITIONS
WHERE `TABLE_SCHEMA` = DATABASE()
AND `TABLE_NAME` = 'wp_db2023'
ORDER BY `PARTITION_ORDINAL_POSITION`;変更前と同じ代表クエリを再実行し、以下を確認する。
EXPLAIN PARTITIONSのpartitionsが対象年に絞られる。- 3 日台別クエリの実行時間が悪化していない。
- 366 日 GROUP BY の実行時間または読み取り対象行数が改善している。
- 日別記事、期間差枚サマリー、期間機種別差枚ランキングの表示が正常である。
年次メンテナンス
自動(推奨・導入後)
初回の RANGE 導入が完了している環境では、アプリの月次 WP-Cron(DailyDataRangePartitionScheduler)が 当年・翌年までの欠落年パーティション を REORGANIZE PARTITION p_future で冪等に追加する。
- 未パーティションの
db2023には触れない(初回 PARTITION は手動のまま)。 p_futureの推定行数(InnoDB のTABLE_ROWSは推定値)が 100,000 を超える場合は自動実行をスキップし、error_log に手動実施を促すメッセージを残す。- 年パーティション(
pYYYY)が 1 つも無い異常スキーマでは自動 REORGANIZE しない。 - 管理画面アクセス時(
admin_init)に cron 登録が間引き同期される。
手動(閾値超過時・Cron 未発火時)
p_future に実データが入り続ける前に、翌年用パーティションを追加する。例: 2028 年分を追加する場合。
sql
ALTER TABLE `wp_db2023`
REORGANIZE PARTITION p_future INTO (
PARTITION p2028 VALUES LESS THAN (2029),
PARTITION p_future VALUES LESS THAN MAXVALUE
);ロールバック
パーティション導入後に問題が出た場合は、メンテナンス窓でパーティションを解除する。
sql
ALTER TABLE `wp_db2023` REMOVE PARTITIONING;大規模テーブルでは解除もテーブル再構築になるため、実行前にバックアップ・影響範囲・復旧時間を確認する。
関連
- db2023 台別データ 読み取りパフォーマンス調査
- DailyDataPerUnit テーブル(db2023)のスキーマ前提
- Issue #2293
- Issue #2341