2026年9月12日

2026年9月12日

WordPressのデータベースを最適化する方法・テーブル最適化とクリーンアップ

はじめに

「管理画面の動作が重くなってきた」「データベースのサイズが大きくなりすぎている」——WordPressのデータベースは長期運用により断片化や不要データが蓄積します。定期的な最適化でサイトのパフォーマンスを維持できます。

症状・原因

WordPressのMySQLデータベースは投稿リビジョン・自動下書き・スパムコメント・削除済み投稿・期限切れTransientが蓄積して肥大化します。テーブルが断片化すると検索クエリが遅くなり、管理画面やフロントエンドの表示速度に影響します。

解決手順

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

-- phpMyAdminのSQLタブで実行
-- テーブルごとのサイズを確認
SELECT
    table_name AS 'テーブル名',
    ROUND(data_length / 1024 / 1024, 2) AS 'データ(MB)',
    ROUND(data_free / 1024 / 1024, 2) AS '未使用(MB)',
    ROUND((data_length + index_length) / 1024 / 1024, 2) AS '合計(MB)'
FROM information_schema.tables
WHERE table_schema = 'wordpress_db'  -- DB名を変更
ORDER BY (data_length + index_length) DESC;

-- Transientの数を確認
SELECT COUNT(*) FROM wp_options
WHERE option_name LIKE '_transient_%';

-- 投稿リビジョンの数を確認
SELECT COUNT(*) FROM wp_posts
WHERE post_type = 'revision';
# WP-CLIでデータベース情報を確認
wp db size
wp db size --tables

# データベースの状態を確認
wp db check

ステップ2:不要データを削除してDBを軽量化する

# WP-CLIで不要データを一括削除
# 投稿リビジョンを削除
wp post delete $(wp post list --post_type=revision --format=ids) --force

# 自動下書きを削除
wp post delete $(wp post list --post_status=auto-draft --format=ids) --force

# ゴミ箱内のデータを削除
wp post delete $(wp post list --post_status=trash --format=ids) --force

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

# 期限切れTransientを削除
wp transient delete --expired
-- SQLで一括削除(phpMyAdminで実行)
-- バックアップ後に実行すること!

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

-- 自動下書きを削除
DELETE FROM wp_posts WHERE post_status = 'auto-draft';

-- ゴミ箱の投稿を削除
DELETE p, pm FROM wp_posts p
LEFT JOIN wp_postmeta pm ON pm.post_id = p.ID
WHERE p.post_status = 'trash';

-- 期限切れTransientを削除
DELETE FROM wp_options
WHERE option_name LIKE '_transient_%'
AND option_name LIKE '_transient_timeout_%';

-- 孤立したpostmetaを削除(投稿のないメタデータ)
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;

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

-- OPTIMIZE TABLE でテーブルの断片化を解消
OPTIMIZE TABLE wp_posts;
OPTIMIZE TABLE wp_postmeta;
OPTIMIZE TABLE wp_options;
OPTIMIZE TABLE wp_comments;
OPTIMIZE TABLE wp_commentmeta;
OPTIMIZE TABLE wp_usermeta;

-- 全テーブルを一括最適化(phpMyAdmin → データベース選択 → 全選択 → 最適化)
# WP-CLIでテーブルを最適化
wp db optimize

# 特定テーブルを指定して最適化
wp db query "OPTIMIZE TABLE wp_posts, wp_postmeta, wp_options;"

# データベースを修復(テーブルが壊れた場合)
wp db repair

ステップ4:インデックスを追加してクエリを高速化する

-- wp_optionsテーブルのautoloadインデックス(よく使われる最適化)
-- autoload='yes'の項目が多い場合に効果的
SELECT COUNT(*), LENGTH(option_value)
FROM wp_options
WHERE autoload = 'yes'
GROUP BY autoload;

-- autoloadオプションのサイズが大きい場合のインデックス追加
-- (通常は既に存在するが念のため確認)
SHOW INDEX FROM wp_options WHERE Key_name = 'autoload';

-- wp_postmetaのmeta_keyにインデックスを追加(カスタムクエリ高速化)
-- 既存インデックスを確認
SHOW INDEX FROM wp_postmeta;

-- meta_key + meta_value の複合インデックス
ALTER TABLE wp_postmeta
ADD INDEX meta_key_value (meta_key(191), meta_value(100));

ステップ5:定期最適化を自動化する

// functions.php: WordPressのCronで定期最適化
add_action( 'wp', function() {
    if ( ! wp_next_scheduled( 'my_db_optimize_event' ) ) {
        wp_schedule_event( time(), 'weekly', 'my_db_optimize_event' );
    }
} );

add_action( 'my_db_optimize_event', function() {
    global $wpdb;

    // 期限切れTransientを削除
    $wpdb->query(
        "DELETE FROM $wpdb->options
         WHERE option_name LIKE '_transient_timeout_%'
         AND option_value < " . time()
    );

    $wpdb->query(
        "DELETE FROM $wpdb->options
         WHERE option_name LIKE '_transient_%'
         AND option_name NOT LIKE '_transient_timeout_%'
         AND option_name NOT IN (
             SELECT CONCAT('_transient_', SUBSTRING(option_name, 20))
             FROM (SELECT option_name FROM $wpdb->options WHERE option_name LIKE '_transient_timeout_%') tmp
         )"
    );

    // テーブルを最適化
    $tables = $wpdb->get_results( "SHOW TABLES", ARRAY_N );
    foreach ( $tables as $table ) {
        $wpdb->query( "OPTIMIZE TABLE {$table[0]}" );
    }

    // 自動下書きを削除(30日以上前のもの)
    $wpdb->query(
        "DELETE FROM $wpdb->posts
         WHERE post_status = 'auto-draft'
         AND post_modified < DATE_SUB(NOW(), INTERVAL 30 DAY)"
    );
} );

注意事項

  • データベースの削除・最適化操作を行う前に必ずバックアップを取得してください。wp db export backup.sqlでエクスポートできます。誤って必要なデータを削除した場合は復元できません。
  • OPTIMIZE TABLEはMyISAMテーブルでは断片化解消が行われますが、InnoDBテーブルでは実質的にはテーブルの再構築(REBUILD)が行われます。大きなテーブルに対しては実行中にDBロックが発生する場合があるため、トラフィックの少ない時間帯に実行してください。
  • 孤立したpostmetaやcommentmetaの削除は慎重に行ってください。プラグインが意図的に投稿なしでメタデータを保存している場合があります。削除後にプラグインの動作確認を行ってください。

まとめ

データベース最適化は「WP-CLIでDB状態確認→不要データ(リビジョン・Transient・ゴミ箱)削除→OPTIMIZE TABLEで断片化解消→インデックス追加でクエリ高速化→Cronで定期自動最適化」の流れで整備します。関連記事:WordPressの不要データを自動的に削除する方法、WordPressのリビジョン数を制限する方法。

お気軽にご相談ください

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