2026年5月20日
2026年5月20日
WordPressのオプションテーブルが肥大化する場合の対処法
はじめに
WordPressサイトが年々重くなっている、データベースが数GBに膨れ上がっている、管理画面の読み込みが遅い。こうした症状の原因の一つがwp_optionsテーブルの肥大化です。放置すると毎回のページ読み込みで大量のオプションをロードし、サイト全体のパフォーマンスに影響します。
症状・原因
wp_optionsテーブルにはautoload='yes'のレコードがあり、WordPressは起動時に全て読み込みます。プラグインをインストール・削除した後も設定データが残ることが多く、数百万件のレコードが蓄積するケースもあります。
主な原因:
- プラグインの削除漏れ:アンインストール時にオプションを削除しないプラグイン
- セッション・一時データ:transientが期限切れ後も残っている
- リビジョンデータ:投稿の自動下書きデータ
- キャッシュシステム:設定値を大量にoptionsに保存するプラグイン
解決手順
ステップ1:現状を把握する
まずautoloadされている全レコードのサイズを確認します。
-- autoload合計サイズの確認
SELECT
COUNT(*) AS count,
SUM(LENGTH(option_value)) / 1024 / 1024 AS total_mb,
SUM(CASE WHEN autoload = 'yes' THEN LENGTH(option_value) ELSE 0 END) / 1024 AS autoload_kb
FROM wp_options;
-- 大きなautoloadレコードを探す
SELECT option_name, LENGTH(option_value) AS size, autoload
FROM wp_options
WHERE autoload = 'yes'
ORDER BY LENGTH(option_value) DESC
LIMIT 20;
ステップ2:期限切れtransientを削除する
# WP-CLIで期限切れtransientを削除
wp transient delete --expired
# 全transientを削除(より積極的)
wp transient delete --all
SQLで直接削除する場合:
-- 期限切れtransientを削除
DELETE FROM wp_options
WHERE option_name LIKE '_transient_timeout_%'
AND option_value < UNIX_TIMESTAMP();
DELETE FROM wp_options
WHERE option_name LIKE '_transient_%'
AND option_name NOT LIKE '_transient_timeout_%'
AND NOT EXISTS (
SELECT 1 FROM (SELECT * FROM wp_options) tmp
WHERE tmp.option_name = CONCAT('_transient_timeout_', SUBSTRING(wp_options.option_name, 12))
);
ステップ3:不要なオプションのautoloadをオフにする
// functions.php で特定オプションのautoloadを無効化
// (プラグインが残した不要なautoloadデータ)
add_action('init', function() {
$options_to_deautoload = [
'woocommerce_session_data',
'unnecessary_plugin_cache',
// 不要なオプション名を追加
];
foreach ($options_to_deautoload as $option) {
if (get_option($option) !== false) {
$value = get_option($option);
delete_option($option);
add_option($option, $value, '', 'no'); // autoload='no'で再登録
}
}
});
WP-CLIで一括変更:
# 特定のオプションのautoloadを無効化
wp eval 'global $wpdb; $wpdb->update(
$wpdb->options,
["autoload" => "no"],
["option_name" => "problematic_option_name"]
);'
ステップ4:不要なオプションを完全削除する
# 特定のプラグインが残したオプションを削除
wp option delete old_plugin_settings
wp option delete old_plugin_cache_data
# パターンマッチで一括削除
wp eval '
global $wpdb;
$wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE \"old_plugin_%\"");
echo "Deleted: " . $wpdb->rows_affected . " rows\n";
'
ステップ5:データベースを最適化する
# wp_optionsテーブルを最適化
wp db query "OPTIMIZE TABLE wp_options;"
# 全テーブルを最適化
wp db optimize
ステップ6:WP-Cron Job Managerで定期クリーンアップ
// functions.php — 週次で自動クリーンアップ
add_action('wp', function() {
if (!wp_next_scheduled('cleanup_options_table')) {
wp_schedule_event(time(), 'weekly', 'cleanup_options_table');
}
});
add_action('cleanup_options_table', function() {
// 期限切れtransientを削除
delete_expired_transients();
// データベースを最適化
global $wpdb;
$wpdb->query("OPTIMIZE TABLE {$wpdb->options}");
});
function delete_expired_transients() {
global $wpdb;
$wpdb->query(
"DELETE a, b FROM {$wpdb->options} a, {$wpdb->options} b
WHERE a.option_name LIKE '_transient_timeout_%'
AND a.option_value < " . time() . "
AND b.option_name = CONCAT('_transient_', SUBSTRING(a.option_name, 20))"
);
}
注意事項
- SQL直接操作の前に必ずデータベースのバックアップを取ってください。
wp_optionsの削除は取り消せません。削除前にオプション名と値を確認しましょう。- アクティブなプラグインのオプションは削除しないでください。
まとめ
wp_optionsテーブルの肥大化はWP-CLIでtransientを削除し、不要なautoloadオプションを無効化することで改善できます。定期クリーンアップも設定しておくと継続的なパフォーマンス維持に効果的です。関連記事:WordPressのデータベース最適化、transientの使い方