2026年6月29日

2026年6月29日

Query Monitorを使ったWordPressのデバッグ・パフォーマンス改善方法

はじめに

WordPressサイトが遅い、エラーが出る、どのプラグインが問題なのか分からない——そんな悩みを解決するのがQuery Monitorです。管理画面上に詳細なデバッグ情報を表示し、SQLクエリの実行時間からPHPエラー、フック実行順序まで可視化できる強力なツールです。

症状・原因

  • ページ読み込みが遅いが、どのクエリが原因か特定できない
  • 特定のプラグインを有効化すると処理が重くなるが証拠がない
  • WP_DEBUGをtrueにしてもエラーの詳細な発生箇所が分からない
  • フックの実行順序やコールバック関数の登録状況を確認したい

解決手順

ステップ1:Query Monitorのインストールと基本パネルの理解

管理画面の「プラグイン → 新規追加」から「Query Monitor」を検索してインストール・有効化します。有効化すると管理バーに実行時間とクエリ数が表示されます。

# WP-CLIでインストールする場合
wp plugin install query-monitor --activate

# ステータス確認
wp plugin status query-monitor

管理バーのパネルをクリックすると以下のタブが表示されます:

  • Queries:全SQLクエリの一覧と実行時間
  • Hooks:フック名と登録されたコールバック
  • PHP Errors:PHPの警告・エラー一覧
  • Request:クエリ変数とテンプレートファイル情報

wp-config.phpに以下を追加すると、ログインしていないユーザーの情報も取得できます:

// wp-config.php
define( 'QM_COOKIE', 'query_monitor_1' );

ステップ2:遅いSQLクエリの特定とEXPLAIN分析

QueryパネルではSQLクエリが実行時間の降順で表示されます。0.05秒以上かかるクエリは赤くハイライトされます。

// functions.php または カスタムプラグイン
// 意図的に遅いクエリを作成してテスト
add_action( 'init', function() {
    global $wpdb;
    
    // インデックスのないカラムで検索(意図的な遅いクエリ例)
    $results = $wpdb->get_results(
        "SELECT * FROM {$wpdb->posts} 
         WHERE post_content LIKE '%キーワード%' 
         AND post_status = 'publish'",
        ARRAY_A
    );
} );

Query MonitorのQueriesタブで遅いクエリを発見したら、EXPLAIN分析でインデックスの使用状況を確認します:

// EXPLAIN分析をWP-CLIで実行
// wp-cli.local.yml に以下の設定が必要な場合あり
global $wpdb;
$explain = $wpdb->get_results(
    "EXPLAIN SELECT * FROM {$wpdb->posts} WHERE post_author = 1"
);
var_dump( $explain );
# MySQL CLIで直接EXPLAIN
mysql -u root -p wordpress -e "EXPLAIN SELECT * FROM wp_posts WHERE post_author = 1\G"

key列がNULLの場合はインデックスが使われていません。wp_postmetameta_valueカラムへの検索は特に注意が必要です。

ステップ3:フック・プラグインのクエリ追跡

Query MonitorのQueriesタブにある「Caller」列は、どの関数・プラグインがSQLクエリを発行したかを示します。

// フックごとのクエリ数を確認するカスタム実装例
add_action( 'all', function( $hook_name ) {
    static $query_counts = [];
    global $wpdb;
    
    if ( ! isset( $query_counts[ $hook_name ] ) ) {
        $query_counts[ $hook_name ] = $wpdb->num_queries;
    }
    
    // クエリが増加したフックを記録
    $diff = $wpdb->num_queries - $query_counts[ $hook_name ];
    if ( $diff > 5 ) {
        error_log( "Hook {$hook_name} fired {$diff} queries" );
    }
}, 10, 1 );

Hooksタブではすべてのフックと登録コールバックが確認できます。特定のフックにどのプラグインがコールバックを登録しているか一目瞭然です:

// 特定フックの登録状況を手動確認
global $wp_filter;

if ( isset( $wp_filter['save_post'] ) ) {
    foreach ( $wp_filter['save_post']->callbacks as $priority => $callbacks ) {
        foreach ( $callbacks as $callback ) {
            echo "Priority {$priority}: ";
            if ( is_array( $callback['function'] ) ) {
                echo get_class( $callback['function'][0] ) . '::' . $callback['function'][1];
            } else {
                echo $callback['function'];
            }
            echo "\n";
        }
    }
}

ステップ4:メモリ使用量とPHPエラーの監視

Query MonitorのOverviewパネルにはページ生成時のメモリ使用量のピーク値が表示されます。

// wp-config.php でメモリ制限を設定
define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );

// デバッグログを有効化
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );   // /wp-content/debug.log に記録
define( 'WP_DEBUG_DISPLAY', false ); // 画面表示はOFF(本番環境)
define( 'SCRIPT_DEBUG', true );   // 圧縮されていないJS/CSSを使用
define( 'SAVEQUERIES', true );    // $wpdb->queries にクエリを記録
// カスタムコードでメモリ使用量をチェック
function check_memory_usage( $hook_name ) {
    $memory_mb = memory_get_usage( true ) / 1024 / 1024;
    if ( $memory_mb > 100 ) {
        error_log( sprintf(
            'High memory usage at %s: %.2f MB',
            $hook_name,
            $memory_mb
        ) );
    }
}
add_action( 'wp_loaded', function() { check_memory_usage( 'wp_loaded' ); } );
add_action( 'wp', function() { check_memory_usage( 'wp' ); } );

PHP ErrorsタブではE_NOTICEE_DEPRECATEDも含む全エラーが表示されます。非推奨関数の使用も早期に発見できます。

ステップ5:WP-CLI統合とカスタムデータパネルの作成

Query MonitorはWP-CLIとの連携や、独自のデバッグデータを表示するカスタムパネルの作成もサポートしています。

# WP-CLIでQuery Monitorの情報を取得
wp eval 'echo QM_Collectors::get("db-queries")->get_data()["total_time"];'

# カスタムWP-CLIコマンドでクエリ分析
wp eval '
global $wpdb;
$wpdb->show_errors();
$results = $wpdb->get_results( "SELECT post_type, COUNT(*) as cnt FROM wp_posts GROUP BY post_type" );
foreach( $results as $row ) {
    WP_CLI::line( $row->post_type . ": " . $row->cnt );
}
'

qm/collectフィルターを使ってカスタムデータをQuery Monitorパネルに表示できます:

// カスタムQuery Monitorコレクターの作成
// /wp-content/mu-plugins/custom-qm-panel.php

class Custom_QM_Collector extends QM_Collector {
    public $id = 'custom-debug';
    
    public function process() {
        // カスタムデータを収集
        $this->data['custom_info'] = [
            'theme'        => get_template(),
            'child_theme'  => get_stylesheet(),
            'active_hooks' => count( $GLOBALS['wp_filter'] ),
            'memory_peak'  => round( memory_get_peak_usage( true ) / 1024 / 1024, 2 ) . ' MB',
        ];
    }
}

// コレクターを登録
add_filter( 'qm/collectors', function( $collectors ) {
    $collectors['custom-debug'] = new Custom_QM_Collector();
    return $collectors;
} );

// 出力パネルを登録
add_filter( 'qm/outputter/html', function( $output, $collectors ) {
    if ( isset( $collectors['custom-debug'] ) ) {
        $output['custom-debug'] = new Custom_QM_Output_Html_Custom( $collectors['custom-debug'] );
    }
    return $output;
}, 10, 2 );

注意事項

  • Query Monitorは本番環境では管理者ユーザーにのみ表示されますが、SAVEQUERIES定数をtrueにすると全ユーザーのリクエストでもクエリが記録されパフォーマンスに影響するため、デバッグ後は必ずfalseに戻してください
  • WP_DEBUG_LOGを有効にした場合、/wp-content/debug.logがブラウザからアクセス可能な場合があります。.htaccessでアクセスを遮断するか、ログファイルのパスをWP_DEBUG_LOGに絶対パスで指定してWebルート外に配置してください
  • カスタムQMコレクターはQM_Collectorクラスを継承しますが、Query Monitorのバージョンアップでクラス構造が変わることがあるため、メジャーバージョン更新時は動作確認を行ってください

まとめ

Query Monitorを活用することで、WordPressのパフォーマンス問題の原因を数分で特定できます。SQLクエリの実行時間、フックの実行状況、PHPエラー、メモリ使用量をひとつのツールで把握できるため、デバッグ効率が大幅に向上します。本番環境へのデプロイ前の最終チェックとしても有効です。

関連記事:WP-CLIを使ったWordPress運用の自動化テクニック

お気軽にご相談ください

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