2026年11月13日

2026年11月13日

Query Monitor Guide: Slow Queries, PHP Errors, Hooks and HTTP Calls

This article is a localized edition of the Japanese original. Read the Japanese original

Query Monitor is a developer plugin that lets you check, from the admin toolbar, the database queries, PHP errors, hooks, outgoing HTTP requests and more that ran while a WordPress page was generated. Because you can narrow things down by "component" to see which plugin or theme is responsible, it is useful for finding out why pages are slow.

This article matches Query Monitor 4.1.1 as of November 2026. According to wordpress.org, it requires WordPress 6.3 or later and PHP 7.4 or later.

Who can see Query Monitor’s output

  • By default, it is shown only to Administrators on single sites and Super Admins on Multisite. Visitors do not see it.
  • To check while logged out or as a non-Administrator, click "Set authentication cookie" in Query Monitor's "Settings" panel. That browser then sees the output even after logging out.
  • According to the official description, Query Monitor does not store the data it collects and does not send it anywhere.

Step 1: Install it

In the admin screen, go to "Plugins" → "Add New Plugin", search for "Query Monitor", install it and activate it. With WP-CLI, do the following:

wp plugin install query-monitor --activate

When activated, Query Monitor creates a symbolic link at wp-content/db.php pointing to its own file. This is a database drop-in that collects more detailed information about queries. It is not created in these cases:

  • wp-content/db.php already exists (for example, another plugin's drop-in)
  • DISALLOW_FILE_MODS is true in wp-config.php, or you set QM_DB_SYMLINK to false
  • The server cannot create symbolic links

You can still see the list of queries without the drop-in. On a single site, Query Monitor's db.php is removed when you deactivate the plugin.

You do not need to add SAVEQUERIES to wp-config.php. If SAVEQUERIES is not defined, Query Monitor sets it to true itself. Conversely, if it is set to false, queries cannot be collected.

Step 2: Read the numbers in the admin toolbar

With Query Monitor active, open a page and the admin toolbar shows an overview of that page: page generation time (how long PHP took to build the page), peak memory usage, and the total time and number of database queries. If there are PHP errors, a warning appears in the admin toolbar.

Click the toolbar item to open the detailed panels. The main panels are:

Panel What it shows
Database Queries Every query that ran. Can be filtered by type, component and caller
Queries by Component Number and time of queries per plugin, theme and core
Duplicate Queries Places where the same query runs many times
Slow Queries Queries that took a long time
PHP Errors Warnings, notices, deprecations and other errors, with the responsible component
Hooks & Actions Actions that fired and the callbacks attached to them
HTTP API Calls Outgoing HTTP requests, response codes and time taken
Timings Processing time measured with qm/start and friends (Step 6)
Template The template file used and the template hierarchy
Environment Information about PHP, the database, WordPress and the web server

Step 3: Find slow queries and the plugin behind them

  1. Open a page that feels slow and open "Queries by Component" from the admin toolbar. It shows which plugins or themes run the most queries or take the most time.
  2. Open "Slow Queries". By default, queries that took more than 0.05 seconds are listed (define QM_DB_EXPENSIVE in wp-config.php to change the threshold).
  3. Open "Duplicate Queries" and check whether the same query runs over and over. This happens, for example, with code that fetches post meta one item at a time inside a loop.
  4. In "Database Queries", look at the "Caller" and "Component" of the queries you are interested in to see which function in which file ran them.

If the cause is a WP_Query in your own code, turning off work it does not need can make it lighter. All of the arguments below are official WP_Query arguments.

<?php
$query = new WP_Query( array(
	'post_type'              => 'product',
	'posts_per_page'         => 10,
	// If you do not paginate, skip the query that counts all rows
	'no_found_rows'          => true,
	// If you do not use post meta or terms, skip loading them in bulk
	'update_post_meta_cache' => false,
	'update_post_term_cache' => false,
) );

Setting no_found_rows to true disables pagination (the total page count). If you do display post meta or terms, setting update_post_meta_cache and the like to false actually increases the number of queries. Compare the query count and time in Query Monitor before and after the change.

You can check the execution plan of a slow query by adding EXPLAIN with WP-CLI's wp db query. Match the table prefix (wp_) to the one shown by wp db prefix.

# Check the execution plan
wp db query "EXPLAIN SELECT meta_value FROM wp_postmeta WHERE post_id = 123 AND meta_key = '_price'"

# Check the indexes and row count of wp_postmeta
wp db query "SHOW INDEX FROM wp_postmeta"
wp db query "SELECT COUNT(*) FROM wp_postmeta"

How to read EXPLAIN and how to think about indexes are covered in detail in how to investigate slow WordPress queries with MySQL EXPLAIN. If a plugin is the cause, review its settings, report it to the author, or consider an alternative plugin.

Step 4: Check PHP errors

The "PHP Errors" panel lists warnings, notices, deprecations and other errors along with the file name, line number, component and call stack. Incorrect use of WordPress functions ("Doing it Wrong") and use of deprecated functions are shown too.

For Ajax and REST API requests where the panel is not shown, Query Monitor adds information to the response headers (this applies to jQuery-initiated Ajax requests and to REST API requests authenticated as a user who can see Query Monitor). Check the headers of the request in the "Network" tab of the browser's developer tools.

If you want to keep errors in a file to review later, enable WordPress's debug log in your development environment. With WP-CLI, do the following:

wp config set WP_DEBUG true --raw --type=constant
wp config set WP_DEBUG_LOG true --raw --type=constant
wp config set WP_DEBUG_DISPLAY false --raw --type=constant

The log is written to wp-content/debug.log. On a live site, set them back to false when you are done. For details, see how to enable WordPress debug mode.

Step 5: Check hooks and outgoing requests

Hooks & Actions

The "Hooks & Actions" panel shows the actions that fired on the page and, for each one, the attached callbacks (functions), priority and component. Use it to check problems such as "my function is not being called" or "another plugin overrides the same hook".

This panel does not show execution time per hook. To measure time, use the method in Step 6.

HTTP API Calls

The "HTTP API Calls" panel shows outgoing requests made with the WordPress HTTP API (wp_remote_get() and so on), with the URL, response code, component and time taken. Failed and erroneous requests get a warning. Plugins that call an external API on every page load can slow pages down.

Step 6: Measure how long your own code takes

To measure where your own code spends time, start and stop a timer with Query Monitor's actions. The results appear in the "Timings" panel.

<?php
do_action( 'qm/start', 'my_heavy_task' );

// The code you want to measure
my_heavy_task();

do_action( 'qm/stop', 'my_heavy_task' );

To record an intermediate point, call qm/lap with the same name. To inspect a value, write it to the "Logs" panel with do_action( 'qm/debug', 'Message' );. You can also use qm/info, qm/warning, qm/error and others; warning and above are also flagged in the admin toolbar.

Because these are do_action() calls, they do not cause errors even when Query Monitor is deactivated.

Notes

  • According to the official description, Query Monitor has only a small effect on page generation time, but it uses a lot of memory on pages with hundreds of queries. Deactivate it when you finish investigating.
  • Even on a live site it is shown only to Administrators, but do your investigation on a staging site whenever possible.
  • For long-running work with a very large number of queries, such as backups or large imports, calling do_action( 'qm/cease' ); makes Query Monitor stop collecting data for the rest of that request.

Summary

  • Check page generation time, memory, and query time and count in the admin toolbar, then dig deeper in the panels
  • For slow pages, identify the responsible plugin and caller with "Queries by Component", "Slow Queries" and "Duplicate Queries"
  • You do not need to define SAVEQUERIES yourself, and setting it to false stops query collection
  • "Hooks & Actions" does not show execution time, so measure time with qm/start and qm/stop
  • Deactivate Query Monitor when you finish investigating

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

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