2026年11月9日
2026年11月9日
WordPressの不要データを自動的に削除する方法・DB肥大化防止
はじめに
「データベースがどんどん大きくなっている」「ゴミ箱やリビジョンの削除を手動でやるのが面倒」——WordPressの不要データを自動削除する仕組みを設定しておけば、DBの肥大化を防いでパフォーマンスを維持できます。
症状・原因
WordPressは投稿を更新するたびにリビジョンを保存し、削除した投稿はゴミ箱に保管されます。また、プラグインが使うTransient(一時データ)も期限切れ後も残り続けることがあります。これらが長期間蓄積するとwp_posts・wp_optionsテーブルが肥大化します。
解決手順
ステップ1:wp-config.phpで基本的なクリーンアップ設定をする
// wp-config.php: 不要データを制御する定数
// ゴミ箱を自動空にする日数(デフォルト30日)
define( 'EMPTY_TRASH_DAYS', 7 ); // 7日後に自動削除
// ゴミ箱を無効化する(即時削除)
// define( 'EMPTY_TRASH_DAYS', 0 ); // 0=ゴミ箱なし
// 投稿リビジョンの保存数を制限
define( 'WP_POST_REVISIONS', 3 ); // 最新3件のみ保持
// define( 'WP_POST_REVISIONS', false ); // リビジョン無効
// 自動保存の間隔(秒)
define( 'AUTOSAVE_INTERVAL', 300 ); // 5分ごと(デフォルト60秒)
// WordPressのCron(擬似Cron)を無効化して外部Cronを使う場合
// define( 'DISABLE_WP_CRON', true );
ステップ2:WP-Cronで定期クリーンアップを設定する
// functions.php: 定期的なクリーンアップジョブを登録
// カスタムスケジュールを追加(毎日深夜)
add_filter( 'cron_schedules', function( $schedules ) {
$schedules['daily_midnight'] = [
'interval' => DAY_IN_SECONDS,
'display' => '毎日',
];
return $schedules;
} );
// クリーンアップイベントをスケジュール
add_action( 'wp', function() {
if ( ! wp_next_scheduled( 'my_cleanup_event' ) ) {
// 翌日の深夜3時に初回実行
$midnight = strtotime( 'tomorrow 3:00 AM' );
wp_schedule_event( $midnight, 'daily', 'my_cleanup_event' );
}
} );
// クリーンアップ処理
add_action( 'my_cleanup_event', 'my_run_cleanup' );
function my_run_cleanup() {
global $wpdb;
// 1. 期限切れTransientを削除
$now = time();
$wpdb->query(
$wpdb->prepare(
"DELETE FROM $wpdb->options
WHERE option_name LIKE %s
AND option_value < %d",
'_transient_timeout_%',
$now
)
);
// 対応するTransient本体も削除
$wpdb->query(
"DELETE FROM $wpdb->options
WHERE option_name LIKE '_transient_%'
AND option_name NOT LIKE '_transient_timeout_%'
AND REPLACE(option_name, '_transient_', '_transient_timeout_')
NOT IN (SELECT option_name FROM $wpdb->options)"
);
// 2. ゴミ箱の投稿(EMPTY_TRASH_DAYS日を超えたもの)を削除
$trash_days = defined( 'EMPTY_TRASH_DAYS' ) ? (int) EMPTY_TRASH_DAYS : 30;
$wpdb->query(
$wpdb->prepare(
"DELETE FROM $wpdb->posts
WHERE post_status = 'trash'
AND post_modified < %s",
gmdate( 'Y-m-d H:i:s', time() - $trash_days * DAY_IN_SECONDS )
)
);
// 3. 自動下書き(24時間以上前)を削除
$wpdb->query(
"DELETE FROM $wpdb->posts
WHERE post_status = 'auto-draft'
AND post_modified < DATE_SUB(NOW(), INTERVAL 1 DAY)"
);
// 4. スパムコメントを削除
$wpdb->query(
"DELETE FROM $wpdb->comments WHERE comment_approved = 'spam'"
);
// 5. 孤立したpostmetaを削除
$wpdb->query(
"DELETE pm FROM $wpdb->postmeta pm
LEFT JOIN $wpdb->posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL"
);
// ログ記録(オプション)
update_option( 'my_last_cleanup', current_time( 'mysql' ) );
}
ステップ3:投稿保存時にリビジョンを制御する
// 投稿タイプ別にリビジョン数を制御
add_filter( 'wp_revisions_to_keep', function( $num, $post ) {
// ニュース投稿は3件のみ
if ( 'news' === $post->post_type ) {
return 3;
}
// 固定ページは5件
if ( 'page' === $post->post_type ) {
return 5;
}
// その他は2件
return 2;
}, 10, 2 );
// 既存の古いリビジョンを一括削除(初回設定時)
add_action( 'admin_init', function() {
if ( ! get_option( 'my_revisions_cleaned' ) ) {
global $wpdb;
// 投稿ごとに最新3件以外のリビジョンを削除
$wpdb->query(
"DELETE FROM $wpdb->posts
WHERE post_type = 'revision'
AND ID NOT IN (
SELECT * FROM (
SELECT ID FROM $wpdb->posts
WHERE post_type = 'revision'
ORDER BY post_modified DESC
LIMIT 9999
) tmp
)"
);
update_option( 'my_revisions_cleaned', true );
}
} );
ステップ4:メディアの未使用ファイルを検出する
// functions.php: 未使用のメディアファイルを検出するツール
add_action( 'admin_menu', function() {
add_management_page(
'未使用メディア一覧',
'未使用メディア',
'manage_options',
'unused-media',
'my_unused_media_page'
);
} );
function my_unused_media_page() {
global $wpdb;
// 投稿・メタで参照されていない添付ファイルを検出
$unused = $wpdb->get_results(
"SELECT p.ID, p.post_title, p.guid
FROM $wpdb->posts p
WHERE p.post_type = 'attachment'
AND p.ID NOT IN (
SELECT pm.meta_value FROM $wpdb->postmeta pm
WHERE pm.meta_key = '_thumbnail_id'
)
AND p.ID NOT IN (
SELECT post_parent FROM $wpdb->posts
WHERE post_parent > 0 AND post_type != 'attachment'
)
LIMIT 50"
);
echo '<div class="wrap"><h1>未使用のメディアファイル</h1>';
echo '<table class="wp-list-table widefat"><thead><tr><th>ID</th><th>タイトル</th><th>URL</th></tr></thead><tbody>';
foreach ( $unused as $item ) {
echo '<tr><td>' . esc_html( $item->ID ) . '</td><td>' . esc_html( $item->post_title ) . '</td><td>' . esc_html( $item->guid ) . '</td></tr>';
}
echo '</tbody></table></div>';
}
ステップ5:クリーンアップ状況を監視する
# WP-CLIでCronジョブの状態を確認
wp cron event list
wp cron event run my_cleanup_event # 手動テスト実行
# 前回実行時刻を確認
wp option get my_last_cleanup
# Transientの残存数を確認
wp db query "SELECT COUNT(*) FROM wp_options WHERE option_name LIKE '_transient_%'"
# リビジョンの残存数
wp db query "SELECT COUNT(*) FROM wp_posts WHERE post_type='revision'"
# DBサイズの変化を記録
wp db size
注意事項
EMPTY_TRASH_DAYSを0に設定するとゴミ箱が無効化され、削除した投稿は即時完全削除されます。誤削除のリスクが高まるため、通常は7〜14日程度の設定を推奨します。- WP-Cronはデフォルトでページが表示されたときに実行されます。トラフィックが少ないサイトでは実行が遅延する場合があります。重要なクリーンアップジョブはサーバーのシステムCronで
wp cron event runを呼び出す方が確実です。 - 孤立したpostmetaの削除は慎重に行ってください。プラグインによっては
post_id=0や存在しない投稿IDにメタデータを意図的に保存する場合があります。
まとめ
不要データの自動削除は「wp-config.phpでEMPTY_TRASH_DAYS・WP_POST_REVISIONS設定→WP-Cronで日次クリーンアップジョブ登録→Transient・ゴミ箱・スパム・孤立postmetaを定期削除→WP-CLIで状況監視」の流れで整備できます。関連記事:WordPressのデータベースを最適化する方法、WordPressのリビジョン数を制限する方法。