2026年5月20日

2026年5月20日

WordPressのデータベースを最適化する方法

はじめに

WordPressを長期間運用するとデータベースに不要なデータが蓄積し、クエリ速度が低下します。リビジョン・スパムコメント・期限切れtransient・孤立したメタデータを定期的に削除することで、データベースのサイズ削減とクエリ高速化が実現できます。

症状・原因

  • データベースのサイズが数GBに膨れ上がっている
  • 管理画面の動作が重くなってきた
  • wp_optionsテーブルが大きくなっている
  • MySQLのスロークエリログに長時間クエリが記録されている

解決手順

ステップ1:データベースの現状を確認する

# データベースサイズの確認
wp db size

# テーブルごとのサイズ確認
wp db size --tables

# 詳細情報(フラグメント等)
wp db query "SELECT table_name, data_length/1024/1024 AS data_mb,
  index_length/1024/1024 AS index_mb,
  data_free/1024/1024 AS free_mb
  FROM information_schema.tables
  WHERE table_schema = DATABASE()
  ORDER BY (data_length + index_length) DESC;"

ステップ2:不要データを一括削除する

# リビジョンの削除(全記事の過去編集履歴)
wp post delete $(wp post list --post_type=revision --format=ids) --force

# スパムコメントの削除
wp comment delete $(wp comment list --status=spam --format=ids) --force

# ゴミ箱の記事を削除
wp post delete $(wp post list --post_status=trash --format=ids) --force

# 期限切れtransientを削除
wp transient delete --expired

# 孤立したメタデータを削除(投稿に紐付かないpostmeta)
wp db query "DELETE pm FROM wp_postmeta pm
  LEFT JOIN wp_posts p ON p.ID = pm.post_id
  WHERE p.ID IS NULL;"

# 孤立したコメントメタを削除
wp db query "DELETE cm FROM wp_commentmeta cm
  LEFT JOIN wp_comments c ON c.comment_ID = cm.comment_id
  WHERE c.comment_ID IS NULL;"

ステップ3:リビジョン数を制限する

// wp-config.php: リビジョンの最大数を設定

// リビジョンを無効化する場合
define('WP_POST_REVISIONS', false);

// リビジョン数を制限する場合(3世代まで保持)
define('WP_POST_REVISIONS', 3);

// 自動保存の間隔を延ばす(デフォルト60秒)
define('AUTOSAVE_INTERVAL', 300); // 5分
// functions.php: 古いリビジョンを定期削除

add_action('wp_scheduled_delete', function (): void {
    global $wpdb;
    // 30日以上前のリビジョンを削除
    $wpdb->query(
        "DELETE p, pm FROM {$wpdb->posts} p
         LEFT JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
         WHERE p.post_type = 'revision'
         AND p.post_date < DATE_SUB(NOW(), INTERVAL 30 DAY)"
    );
});

ステップ4:wp_optionsテーブルを最適化する

# autoloadされているオプションのサイズを確認
wp db query "SELECT option_name, length(option_value) as size
  FROM wp_options
  WHERE autoload = 'yes'
  ORDER BY size DESC
  LIMIT 20;"

# 不要なtransientを削除(transientはoption_nameに _transient_ が含まれる)
wp db query "DELETE FROM wp_options
  WHERE option_name LIKE '_transient_%'
  OR option_name LIKE '_site_transient_%';"

# autoloadの重いオプションをno-autoloadに変更(使用頻度の低いもの)
# wp option update [option_name] --autoload=no は対象を調査してから実施

ステップ5:テーブルを最適化してフラグメントを解消する

# WP-CLI でテーブル最適化
wp db optimize

# または個別テーブルを指定
wp db query "OPTIMIZE TABLE wp_posts, wp_postmeta, wp_options, wp_comments;"

# 自動最適化スクリプト(cronで月1回実行)
#!/bin/bash
WP_PATH="/var/www/html"

# 不要データ削除
wp --path="$WP_PATH" post delete \
  $(wp --path="$WP_PATH" post list --post_type=revision --format=ids) --force 2>/dev/null
wp --path="$WP_PATH" transient delete --expired

# テーブル最適化
wp --path="$WP_PATH" db optimize

echo "Database optimization completed: $(date)"
# crontab: 月1回データベース最適化
0 3 1 * * /bin/bash /scripts/db_optimize.sh >> /var/log/db_optimize.log 2>&1

注意事項

  • リビジョンを削除する前にバックアップを取ってください。削除したリビジョンは復元できません
  • OPTIMIZE TABLE はMyISAMテーブルに最も効果的です。InnoDBでは ALTER TABLE ... ENGINE=InnoDB が同等の効果を持ちます
  • wp_optionsのautoload=yesを安易に変更するとサイトが壊れる可能性があります。変更前に該当オプションが何に使われているか確認してください

まとめ

wp post delete でリビジョン・ゴミ箱を削除し、wp transient delete --expired で期限切れtransientを削除します。wp-config.phpWP_POST_REVISIONS を3〜5に制限して新たなリビジョン蓄積を防ぎます。月1回cronで wp db optimize を実行してテーブルのフラグメントを解消します。

お気軽にご相談ください

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