WordPress データベース重い問題を完全解決!原因から最適化まで徹底ガイド

Web

「WordPressサイトがどんどん遅くなってきた…」

「管理画面の表示に10秒以上かかる」

「記事の保存や公開がタイムアウトする」

「プラグインを減らしても改善しない」

その原因、データベースの肥大化と最適化不足かもしれません!

WordPressは使い続けるとデータベースにゴミデータが蓄積し、パフォーマンスが著しく低下することがあります。

この記事では、WordPressデータベースが重くなる原因から、具体的な最適化方法まで、実践的に解説していきます!

スポンサーリンク

まず確認!データベースの現状を把握する

データベースサイズの確認方法

phpMyAdminで確認

-- データベース全体のサイズ確認
SELECT 
    table_schema AS 'データベース名',
    ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'サイズ(MB)'
FROM information_schema.tables
WHERE table_schema = 'your_wordpress_db'
GROUP BY table_schema;

-- テーブルごとのサイズ確認
SELECT 
    table_name AS 'テーブル名',
    ROUND(((data_length + index_length) / 1024 / 1024), 2) AS 'サイズ(MB)',
    table_rows AS '行数'
FROM information_schema.tables
WHERE table_schema = 'your_wordpress_db'
ORDER BY (data_length + index_length) DESC;

WP-CLIで確認(SSH接続可能な場合)

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

# 各テーブルのサイズを詳細表示
wp db query "SELECT table_name, ROUND(((data_length + index_length) / 1024 / 1024), 2) AS size_mb FROM information_schema.tables WHERE table_schema = DATABASE() ORDER BY size_mb DESC;"

問題のあるテーブルを特定

肥大化しやすいテーブルTOP5:

テーブル名内容肥大化の原因
wp_posts投稿・ページリビジョン、自動下書き
wp_postmeta投稿メタデータ不要なカスタムフィールド
wp_options設定データtransient、autoload
wp_commentsコメントスパムコメント
wp_usermetaユーザーメタセッション、プラグインデータ

WordPressデータベースが重くなる10大原因

1. リビジョンの蓄積

-- リビジョン数の確認
SELECT COUNT(*) as revision_count 
FROM wp_posts 
WHERE post_type = 'revision';

-- 記事ごとのリビジョン数
SELECT 
    p.ID,
    p.post_title,
    COUNT(r.ID) as revision_count
FROM wp_posts p
LEFT JOIN wp_posts r ON r.post_parent = p.ID AND r.post_type = 'revision'
WHERE p.post_type IN ('post', 'page')
GROUP BY p.ID
HAVING revision_count > 10
ORDER BY revision_count DESC;

2. 自動下書きの放置

-- 自動下書きの確認
SELECT COUNT(*) 
FROM wp_posts 
WHERE post_status = 'auto-draft';

-- 1ヶ月以上前の自動下書き
SELECT COUNT(*) 
FROM wp_posts 
WHERE post_status = 'auto-draft' 
  AND post_date < DATE_SUB(NOW(), INTERVAL 1 MONTH);

3. Transientの肥大化

-- Transientの数と容量確認
SELECT 
    COUNT(*) as transient_count,
    SUM(LENGTH(option_value)) / 1024 / 1024 as size_mb
FROM wp_options 
WHERE option_name LIKE '%_transient_%';

-- 期限切れTransientの確認
SELECT COUNT(*) 
FROM wp_options 
WHERE option_name LIKE '_transient_timeout_%' 
  AND option_value < UNIX_TIMESTAMP();

4. スパムコメントとゴミ箱

-- スパム・ゴミ箱コメント数
SELECT 
    comment_approved,
    COUNT(*) as count
FROM wp_comments
WHERE comment_approved IN ('spam', 'trash')
GROUP BY comment_approved;

5. プラグインの残骸データ

-- 孤立したpostmetaデータ
SELECT COUNT(*) 
FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;

-- 使われていないoptionsデータ(autoload)
SELECT 
    option_name,
    LENGTH(option_value) / 1024 as size_kb,
    autoload
FROM wp_options
WHERE autoload = 'yes'
  AND option_name NOT LIKE '%wordpress%'
  AND option_name NOT LIKE '%wp_%'
ORDER BY LENGTH(option_value) DESC
LIMIT 20;

今すぐできる!データベース最適化10の方法

方法1:リビジョンの削除と制限

既存リビジョンの削除

-- 全リビジョンを削除(危険:バックアップ必須)
DELETE FROM wp_posts WHERE post_type = 'revision';

-- 各記事の最新3件以外のリビジョンを削除
DELETE r1 FROM wp_posts r1
INNER JOIN wp_posts r2 
WHERE r1.post_parent = r2.post_parent
  AND r1.post_type = 'revision'
  AND r2.post_type = 'revision'
  AND r1.ID < r2.ID
  AND (
    SELECT COUNT(*) FROM wp_posts r3
    WHERE r3.post_parent = r1.post_parent
      AND r3.post_type = 'revision'
      AND r3.ID >= r1.ID
  ) > 3;

wp-config.phpでリビジョン制限

// リビジョンを3つまでに制限
define('WP_POST_REVISIONS', 3);

// リビジョンを完全無効化(非推奨)
define('WP_POST_REVISIONS', false);

// リビジョンの自動保存間隔を変更(デフォルト60秒)
define('AUTOSAVE_INTERVAL', 300); // 5分

方法2:自動下書きのクリーンアップ

-- 1週間以上前の自動下書きを削除
DELETE FROM wp_posts 
WHERE post_status = 'auto-draft' 
  AND post_date < DATE_SUB(NOW(), INTERVAL 7 DAY);

-- タイトルのない自動下書きを削除
DELETE FROM wp_posts 
WHERE post_status = 'auto-draft' 
  AND post_title = '';

方法3:Transientの最適化

-- 期限切れTransientを削除
DELETE FROM wp_options 
WHERE option_name LIKE '_transient_timeout_%' 
  AND option_value < UNIX_TIMESTAMP();

-- 関連するTransientデータも削除
DELETE FROM wp_options 
WHERE option_name LIKE '_transient_%' 
  AND option_name NOT IN (
    SELECT CONCAT('_transient_', SUBSTR(option_name, 20)) 
    FROM (SELECT option_name FROM wp_options) AS temp 
    WHERE option_name LIKE '_transient_timeout_%'
  );

-- サイトTransientも同様に処理
DELETE FROM wp_options 
WHERE option_name LIKE '_site_transient_timeout_%' 
  AND option_value < UNIX_TIMESTAMP();

方法4:wp_optionsテーブルの最適化

-- autoloadの最適化(大きいデータをautoload='no'に)
UPDATE wp_options 
SET autoload = 'no' 
WHERE autoload = 'yes' 
  AND LENGTH(option_value) > 10000
  AND option_name NOT IN (
    'active_plugins', 'stylesheet', 'template', 
    'current_theme', 'WPLANG', 'home', 'siteurl'
  );

-- 不要なプラグインオプションの削除例
DELETE FROM wp_options 
WHERE option_name LIKE '%_backup_%'
   OR option_name LIKE '%_old_%'
   OR option_name LIKE '%_temp_%';

方法5:コメント関連のクリーンアップ

-- スパムコメントを完全削除
DELETE FROM wp_comments WHERE comment_approved = 'spam';

-- 30日以上前のゴミ箱コメントを削除
DELETE FROM wp_comments 
WHERE comment_approved = 'trash' 
  AND comment_date < DATE_SUB(NOW(), INTERVAL 30 DAY);

-- 孤立したコメントメタを削除
DELETE FROM wp_commentmeta 
WHERE comment_id NOT IN (SELECT comment_id FROM wp_comments);

方法6:メタデータのクリーンアップ

-- 孤立したpostmetaを削除
DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;

-- 孤立したusermetaを削除
DELETE um FROM wp_usermeta um
LEFT JOIN wp_users u ON u.ID = um.user_id
WHERE u.ID IS NULL;

-- 重複したpostmetaを削除(同じpost_id, meta_keyの組み合わせ)
DELETE pm1 FROM wp_postmeta pm1
INNER JOIN wp_postmeta pm2 
WHERE pm1.meta_id < pm2.meta_id
  AND pm1.post_id = pm2.post_id
  AND pm1.meta_key = pm2.meta_key;

方法7:テーブルの最適化(OPTIMIZE)

-- 全テーブルを最適化
OPTIMIZE TABLE wp_posts, wp_postmeta, wp_options, wp_comments, wp_commentmeta, wp_users, wp_usermeta;

-- または個別に実行
OPTIMIZE TABLE wp_posts;
OPTIMIZE TABLE wp_postmeta;
OPTIMIZE TABLE wp_options;

方法8:インデックスの追加

-- よく使われるクエリ用のインデックス追加
ALTER TABLE wp_postmeta ADD INDEX meta_key_value (meta_key(191), meta_value(100));
ALTER TABLE wp_posts ADD INDEX post_status_type (post_status, post_type);
ALTER TABLE wp_options ADD INDEX autoload (autoload);

-- 既存インデックスの確認
SHOW INDEX FROM wp_posts;
SHOW INDEX FROM wp_postmeta;

方法9:キャッシュプラグインの活用

おすすめプラグイン設定:

// wp-config.phpでの設定
define('WP_CACHE', true);

// オブジェクトキャッシュの有効化
define('WP_CACHE_KEY_SALT', 'your_unique_string');

// データベースクエリキャッシュ
define('QUERY_CACHE_TYPE', 1);
define('QUERY_CACHE_SIZE', '256M');

方法10:定期的な自動メンテナンス

// functions.phpに追加
// 週次でTransientをクリーンアップ
if (!wp_next_scheduled('cleanup_expired_transients')) {
    wp_schedule_event(time(), 'weekly', 'cleanup_expired_transients');
}

add_action('cleanup_expired_transients', function() {
    global $wpdb;
    $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_%' AND option_value < UNIX_TIMESTAMP()");
    $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_site_transient_timeout_%' AND option_value < UNIX_TIMESTAMP()");
});

// 月次でリビジョンを削除
if (!wp_next_scheduled('cleanup_old_revisions')) {
    wp_schedule_event(time(), 'monthly', 'cleanup_old_revisions');
}

add_action('cleanup_old_revisions', function() {
    global $wpdb;
    $wpdb->query("DELETE FROM {$wpdb->posts} WHERE post_type = 'revision' AND post_date < DATE_SUB(NOW(), INTERVAL 60 DAY)");
});

プラグインを使った最適化

WP-Optimize(最も人気)

主な機能:

  • データベーステーブルの最適化
  • リビジョン・下書きの削除
  • スケジュール設定可能
  • 画像圧縮機能付き

設定のポイント:

✅ リビジョンをクリーン(最新3件を保持)
✅ 自動下書きを削除
✅ ゴミ箱を空にする
✅ Transientを削除
✅ 毎週自動実行

WP-Sweep

特徴:

  • より詳細なクリーニング
  • 安全性重視(外部キー制約を考慮)
  • 削除前のプレビュー機能

Advanced Database Cleaner

特徴:

  • 孤立データの検出が優秀
  • プラグイン/テーマごとの分析
  • スケジュール機能

重いデータベースの緊急対処法

即効性のある対処法

-- 1. 最も効果的:全リビジョン削除
DELETE FROM wp_posts WHERE post_type = 'revision';

-- 2. Transientを全削除(キャッシュクリア)
DELETE FROM wp_options WHERE option_name LIKE '%_transient_%';

-- 3. autoloadを減らす
UPDATE wp_options SET autoload = 'no' 
WHERE autoload = 'yes' 
  AND option_name NOT LIKE 'wp_%' 
  AND option_name NOT LIKE 'widget_%';

-- 4. テーブル最適化
OPTIMIZE TABLE wp_options, wp_posts, wp_postmeta;

パフォーマンス測定

// functions.phpに追加してクエリ時間を測定
add_action('wp_footer', function() {
    if (current_user_can('administrator')) {
        global $wpdb;
        echo "<!-- Queries: {$wpdb->num_queries} | ";
        echo "Load Time: " . timer_stop(0) . "s -->";
    }
});

// wp-config.phpでクエリログ有効化
define('SAVEQUERIES', true);

データベース構造の最適化

テーブルエンジンの確認と変換

-- MyISAMからInnoDBへ変換(推奨)
ALTER TABLE wp_posts ENGINE=InnoDB;
ALTER TABLE wp_postmeta ENGINE=InnoDB;
ALTER TABLE wp_options ENGINE=InnoDB;
ALTER TABLE wp_comments ENGINE=InnoDB;

-- 全テーブルを一括変換
SELECT CONCAT('ALTER TABLE ', table_name, ' ENGINE=InnoDB;') 
FROM information_schema.tables 
WHERE table_schema = 'your_database' 
  AND engine = 'MyISAM';

文字セットの統一

-- UTF8MB4への変換(絵文字対応)
ALTER DATABASE your_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- テーブルごとに変換
ALTER TABLE wp_posts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE wp_postmeta CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

予防策:データベースを重くしない10のルール

設定による予防

// wp-config.phpでの設定
// 1. リビジョン制限
define('WP_POST_REVISIONS', 3);

// 2. 自動保存間隔
define('AUTOSAVE_INTERVAL', 300);

// 3. ゴミ箱の自動削除
define('EMPTY_TRASH_DAYS', 7);

// 4. メモリ制限の増加
define('WP_MEMORY_LIMIT', '256M');
define('WP_MAX_MEMORY_LIMIT', '512M');

// 5. データベース修復モード
define('WP_ALLOW_REPAIR', true);

定期メンテナンスのスケジュール

頻度作業内容
毎日Transientの削除
週次スパムコメント削除、自動下書き削除
月次リビジョン削減、テーブル最適化
3ヶ月完全バックアップ後の大規模クリーニング

トラブルシューティング

よくある問題と解決法

問題1:最適化してもすぐに重くなる

-- 原因調査:どのテーブルが増えているか
SELECT 
    table_name,
    table_rows,
    data_length / 1024 / 1024 as data_mb
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY table_rows DESC;

問題2:特定のプラグインが原因の場合

-- プラグイン関連のオプションを検索
SELECT option_name, LENGTH(option_value) / 1024 as size_kb
FROM wp_options
WHERE option_name LIKE '%plugin_name%'
ORDER BY LENGTH(option_value) DESC;

まとめ – 軽快なWordPressを維持しよう!

WordPressデータベースの重い問題について、原因から解決方法まで詳しく解説してきました。

重要ポイント:

  • リビジョンとTransientが主な原因
  • 定期的なクリーンアップが必須
  • wp-config.phpでの予防設定が効果的
  • プラグインを使えば自動化も可能
  • バックアップしてから最適化を実行

即効性のある対策TOP3:

  1. リビジョンの削除
  2. Transientのクリア
  3. テーブルのOPTIMIZE実行

データベースの最適化は、サイトの表示速度に直結する重要な作業です。

定期的なメンテナンスを習慣化して、常に快適なWordPressサイトを維持しましょう!

コメント

タイトルとURLをコピーしました