【入門編】実務中級者向け:wp_optionsテーブルの肥大化がクエリに与える影響と対策 – WordPress 内部コア・データベース構造とパフォーマンス最適化解析バイブル

こんにちは!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引数でオートロードの有無をコントロールできるんです。

  • オプションを安全に更新し、オートロードを無効化する例
  • 毎回読み込む必要がない大きなデータ(例:外部APIの一時キャッシュやログなど)は、
  • 必ず ‘no’ を指定してオートロードから外しましょう。
  • /

    $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のパフォーマンスチューニングの基礎はバッチリマスターできていますよ!自信を持って次の開発に臨んでくださいね。

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