こんにちは!WordPressの裏側の仕組みやデータベースの挙動に興味を持ってくれて嬉しいです。他のプログラミング言語やフレームワークを触ったことがある人ほど、「WordPressって、なんだか裏で色々な動きをしているな…?」と気付くはずです。
今回は、実務でも本当によくあるトラブルであり、かつパフォーマンス低下の元凶になりやすい「`wp_options`テーブルの肥大化とオートロード(Autoload)」について、コアの内部構造を紐解きながら一緒に見ていきましょう。
ここをクリアすれば、データベース全体の健康状態を見極める目が養われますよ。一緒にバッチリマスターしていきましょう!
—
1. なぜ `wp_options` が重くなるのか?(内部コアの挙動を知る)
WordPressには、サイトの設定やプラグインのデータを保存するために `wp_options` という非常に重要なテーブルが用意されています。
[ リクエスト発生 ]
↓
[ wp_load初期化 ]
↓
SELECT FROM wp_options WHERE autoload = ‘yes’ ← ★ココがボトルネック!
↓
[ メモリへ全展開 ( wp_load_alloptions ) ]
他の言語のORMやフレームワーク(LaravelやDjangoなど)を経験した方だと、「必要な時に必要なクエリを投げるべきでは?」と思いますよね。
しかしWordPressの歴史的背景と後方互換性の維持から、WordPressはリクエストが走るたびに、`autoload = ‘yes’` が設定されているすべてのオプションデータを一度に読み込み、PHPのメモリ(キャッシュ機構)に保持するという挙動をとります。
イメージ図:オートロードの罠
正常な状態(軽量):
[小規模オプション A] [小規模オプション B] [小規模オプション C]
合計:数十KB (一瞬でメモリへ)
肥大化した状態(重量カルテ):
[トランザクションログ] [古いアクセス解析データ] [巨大なJSON] [ゴミデータ…]
合計:数MB〜数十MB (毎リクエストごとにこれを読み込む地獄…)
つまり、「autoload = ‘yes’」のデータが増えれば増えるほど、トップページを表示するだけでもデータベースとPHPのメモリを無駄に食い潰してしまうことになるのです。これが「サイト全体がなんとなく重い」という現象を引き起こす最大の原因の一つです。
—
2. 現状を把握しよう:オートロードデータのサイズを調べるSQL
まずは、あなたのサイトの `wp_options` がどれくらい肥大化しているか、実際のデータを見てみましょう。
データベース(phpMyAdminやWP-CLIなど)に接続して、以下のクエリを流してみてください。
— オートロードされているオプションの合計サイズ(バイト単位)を計算する
SELECT
SUM(LENGTH(option_value)) / 1024 / 1024 AS autoload_size_mb,
COUNT() AS autoload_count
FROM wp_options
WHERE autoload = ‘yes’;
もし、この `autoload_size_mb` が 1MB〜2MBを超えている場合、黄色信号です。5MBを超えているなら、明らかなパフォーマンス劣化を引き起こしている可能性が高いです。
さらに、「どのオプションがメモリを食っているのか?」を特定するためには、以下のクエリが役立ちます。
— 容量が大きいオートロードオプションのトップ20を抽出
SELECT
option_name,
ROUND(LENGTH(option_value) / 1024, 2) AS size_kb
FROM wp_options
WHERE autoload = ‘yes’
ORDER BY size_kb DESC
LIMIT 20;
プラグインをアンインストールした際の名残(ゴミデータ)が、そのまま `autoload = ‘yes’` のこままで残っているケースが本当に多いんですよね。
—
3. 実践!肥大化したオプションをクリーンアップする
原因が分かったら、次は対策です。
不要なオプションは削除するか、どうしても必要なものであれば オートロードを無効(`no`) に設定変更するのが基本アプローチになります。
コード例:安全なオプションの更新とオートロードの制御
WordPressには、オプションの値を更新する `update_option()` という便利な関数があります。実はこの関数、第4引数でオートロードの有無をコントロールできるんです。
/
$option_name = ‘my_heavy_external_data’;
$option_value = [ ‘logged_at’ => time(), ‘data’ => ‘…巨大なデータ…’ ];
// 第4引数に ‘no’ を指定することで、autoloadカラムが ‘no’ で保存されます。
// これにより、毎リクエスト時のメモリ消費を防ぎます。
update_option( $option_name, $option_value, ‘no’ );
💡 コードの解説とポイント
他の言語から来た人がやってしまいがちなのが、「とりあえず `add_option()` や `update_option()` を引数なしで呼んでしまう」ミスです。
ドキュメントをよく見ると分かりますが、`update_option` の第4引数のデフォルトはプラグインやバージョンによって挙動が異なる場合があるため、「毎リクエストで本当に必要か?」を常に問い、不要なら明示的に `’no’` を渡すのがシニアエンジニアの嗜みです。
—
4. 陥りがちな文法・設計エラーとアンチパターン
ここで、実務でやりがちな失敗例を見ておきましょう。
アンチパターン:コード内で毎回 `autoload = ‘no’` のオプションを無理やり全件取得する
「オートロードを切ったはいいけど、データが必要になった時はどうするの?」という疑問が湧きますよね。
// 【NGな例】 autoload = ‘no’ なのに、毎回ワイルドカードで無理やり探そうとする
// これをやるとインデックスが効かず、テーブル全体スキャン(Full Table Scan)になり、
// 逆にデータベースへ深刻な負荷を与えます。
正しいアプローチ
オートロードを `no` に設定したオプションは、「必要なその瞬間(特定の画面や処理の時)」に、キー名を名指し(ダイレクト)で取得します。
まとめ
いかがでしたでしょうか?
- WordPressは毎リクエスト時、`autoload = ‘yes’` のオプションをメモリに全展開している
- 使っていないプラグインのゴミデータなどが原因で、ここが肥大化するとサイト全体が重くなる
- 頻繁に使わない大きなデータは、明示的に `update_option( …, …, ‘no’ )` でオートロードを切る
- 取得する時はキー名を指定し、インデックスを最大限に活かす
この仕組みを理解しているだけで、フロントエンドのコードをいじらなくても「データベースの最適化だけでサイトが劇的に速くなった!」という感動を味わうことができます。
ここをクリアできれば、もうWordPressのパフォーマンスチューニングの基礎はバッチリマスターできていますよ!自信を持って次の開発に臨んでくださいね。