2026年8月30日

2026年8月30日

WordPressのリビジョンをデータベースから削除する方法

はじめに

WordPressは投稿を保存するたびにリビジョンを作成します。長期運用サイトでは1記事に数十件のリビジョンが蓄積し、wp_postsテーブルが肥大化します。リビジョンを削除することでDBサイズを大幅に削減でき、クエリのパフォーマンスが向上します。

症状・原因

  • wp_postsテーブルのpost_type='revision'が投稿本体より多い
  • データベースの最適化をしてもwp_postsが大きいまま
  • 1記事あたり30〜50件のリビジョンが存在する
  • バックアップファイルが不必要に大きい

解決手順

ステップ1:リビジョンの現状を把握する

# リビジョン総数を確認
wp post list --post_type=revision --format=count

# リビジョンのサイズ確認(MB単位)
wp db query "SELECT COUNT(*) AS count,
    ROUND(SUM(LENGTH(post_content))/1024/1024, 2) AS content_MB
FROM wp_posts WHERE post_type = 'revision';"

# 投稿ごとのリビジョン数(多い順上位20件)
wp db query "SELECT post_parent,
    (SELECT post_title FROM wp_posts WHERE ID = r.post_parent) AS title,
    COUNT(*) AS revision_count
FROM wp_posts r
WHERE post_type = 'revision'
GROUP BY post_parent
ORDER BY revision_count DESC
LIMIT 20;"

# リビジョンと本体の件数比較
wp db query "SELECT post_type, COUNT(*) AS count
FROM wp_posts
WHERE post_type IN ('post', 'page', 'revision')
GROUP BY post_type;"

ステップ2:WP-CLI でリビジョンを削除する

# 全リビジョンを削除(シンプルな方法)
wp post delete \
    $(wp post list --post_type=revision --field=ID --format=ids) \
    --force --quiet

# 件数が多い場合は分割削除(500件ずつ)
while true; do
    IDS=$(wp post list --post_type=revision \
        --field=ID --format=ids --number=500)
    [ -z "$IDS" ] && break
    wp post delete $IDS --force --quiet
    echo "Deleted batch of 500 revisions"
done

# 削除後に件数確認
wp post list --post_type=revision --format=count

# 特定投稿のリビジョンのみ削除(投稿ID=123のリビジョン)
wp post delete \
    $(wp db query "SELECT ID FROM wp_posts
     WHERE post_type='revision' AND post_parent=123" \
     --skip-column-names) \
    --force --quiet

ステップ3:SQL で直接削除する

-- バックアップ取得後に実行すること

-- ① 全リビジョンを削除
DELETE FROM wp_posts WHERE post_type = 'revision';

-- ② 自動保存(autosave)のみ削除
DELETE FROM wp_posts
WHERE post_type = 'revision'
  AND post_name LIKE '%-autosave-v1';

-- ③ 一定期間より古いリビジョンを削除(30日以上前)
DELETE FROM wp_posts
WHERE post_type = 'revision'
  AND post_modified < DATE_SUB(NOW(), INTERVAL 30 DAY);

-- ④ 各投稿の最新3件以外のリビジョンを削除
DELETE FROM wp_posts
WHERE post_type = 'revision'
  AND ID NOT IN (
    SELECT * FROM (
        SELECT ID FROM wp_posts r
        WHERE r.post_type = 'revision'
        ORDER BY r.post_modified DESC
        LIMIT 999999
    ) AS keep
  );

-- ⑤ 削除後に孤立したポストメタを削除
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON pm.post_id = p.ID
WHERE p.ID IS NULL;

ステップ4:今後のリビジョン蓄積を防ぐ設定

// wp-config.php: リビジョン保存数を制限

// 最新3件のみ保持
define('WP_POST_REVISIONS', 3);

// リビジョンを完全に無効化(慎重に検討)
// define('WP_POST_REVISIONS', false);

// 自動保存間隔を延長(デフォルト60秒→5分)
define('AUTOSAVE_INTERVAL', 300);

// functions.php: 投稿タイプ別にリビジョン数を制御
add_filter('wp_revisions_to_keep', function(int $num, WP_Post $post): int {
    return match($post->post_type) {
        'post'       => 5,   // ブログ記事: 5件
        'page'       => 10,  // 固定ページ: 10件
        'product'    => 3,   // カスタム投稿: 3件
        default      => 3,
    };
}, 10, 2);

ステップ5:削除後のテーブル最適化と定期メンテナンス

# テーブルの最適化(OPTIMIZE TABLE)
wp db optimize
# または直接SQL
wp db query "OPTIMIZE TABLE wp_posts, wp_postmeta;"

# 削除・最適化後のサイズ確認
wp db size --tables | grep wp_posts

# 定期削除スクリプト(cron 登録)
# /usr/local/bin/wp-revision-cleanup.sh:
WP_PATH="/var/www/html"
MAX_REVISIONS=3

wp --path="$WP_PATH" db query "
DELETE FROM wp_posts
WHERE post_type = 'revision'
  AND ID NOT IN (
    SELECT id FROM (
        SELECT r.ID AS id
        FROM wp_posts r
        INNER JOIN (
            SELECT post_parent,
                MAX(post_modified) as max_date
            FROM wp_posts
            WHERE post_type = 'revision'
            GROUP BY post_parent
        ) latest ON r.post_parent = latest.post_parent
        WHERE r.post_type = 'revision'
        ORDER BY r.post_parent, r.post_modified DESC
    ) AS keep_revisions
);"

wp --path="$WP_PATH" db query \
    "OPTIMIZE TABLE wp_posts, wp_postmeta;"
echo "[$(date)] Revision cleanup complete"

注意事項

  • リビジョンを削除すると過去の編集履歴が完全に失われます。コンテンツの安全が確認できている場合のみ実行してください
  • wp post deleteコマンドは1件ずつWordPressのフックを通じて削除するため、件数が多いと時間がかかります。数万件ある場合はSQL直接削除の方が高速です
  • AUTOSAVE_INTERVALを長くしすぎると、ブラウザのクラッシュ時に編集内容が失われるリスクが高まります。300秒(5分)程度が実用的な範囲です

まとめ

リビジョン削除は①wp post list --post_type=revision --format=countSUM(LENGTH(post_content))で現状を定量把握、②WP-CLIのwp post delete --forceで分割削除(大量の場合はwhileループ)、③DELETE FROM wp_posts WHERE post_type='revision'で全削除または期間指定削除・孤立ポストメタも合わせて削除、④WP_POST_REVISIONS=3定数とwp_revisions_to_keepフィルターで今後の蓄積を制限、⑤削除後にOPTIMIZE TABLEでテーブルフラグメンテーションを解消します。

お気軽にご相談ください

お見積りへ お問い合わせへ