The autoload feature loads and caches all autoloaded options, if available, or all options. The default option is to autoload, and over time when the wp_options
table grows, this degrades performance.
How to identify a slow WordPress query on wp_options
Even though our MySQL servers are heavily InnoDB optimized, I noticed and identified the following slow query in our log. It's related to the WordPress wp_options
table:
# Time: 140502 12:17:44
# User@Host: db-name[db-name] @ webserver.example.com [1.1.1.11]
# Query_time: 3.491801 Lock_time: 0.000049 Rows_sent: 1337 Rows_examined: 33927
SET timestamp=1399025864;
SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes';
So that is almost 3.5 seconds to examine 33927 and send 1337 rows...
The wp_options
table description is as follows:
mysql> desc wp_options;
+--------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------------+------+-----+---------+----------------+
| option_id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| option_name | varchar(64) | NO | UNI | | |
| option_value | longtext | NO | | NULL | |
| autoload | varchar(20) | NO | MUL | yes | |
+--------------+---------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
The only values for autoload are 'yes
' and 'no
', so why a varchar(20)
field type? Oh well, that's a whole other issue...
Examining the slow autoload query in WordPress
You can use MySQL's EXPLAIN to examine queries and their structure. MySQL EXPLAIN is used to obtain a query execution plan (that is, an explanation of how MySQL would execute a query).
While examining the autoload-query, you'll notice that there is no index present on the autoload column:
mysql> explain SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes';
+----+-------------+------------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+-------+-------------+
| 1 | SIMPLE | wp_options | ALL | NULL | NULL | NULL | NULL | 33927 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+-------+-------------+
1 row in set (0.00 sec)
Again the 33927 rows.
Optimize wp_options with an autoload index
You can optimize the WordPress wp_options table simply by adding an index:
mysql> ALTER TABLE `wp_options` ADD INDEX (`autoload`);
Query OK, 33927 rows affected (0.70 sec)
Records: 33927 Duplicates: 0 Warnings: 0
and we examine the same query again:
mysql> explain SELECT option_name, option_value FROM wp_options WHERE autoload = 'yes';
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------------+
| 1 | SIMPLE | wp_options | ref | autoload | autoload | 62 | const | 1508 | Using where |
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------------+
1 row in set (0.00 sec)
Now there are only 1508 rows left!
It's important to optimize MySQL with indices, and how to improve InnoDB performance in MySQL.
On Make WordPress Core Trac, multiple tickets exist requesting this index to be added in WordPress Core:
- Add index to wp_options to aid/improve performance
- WordPress wp_options autoload micro-optimization (referencing this very article)
- wp_options and MySQL's "log-queries-not-using-indexes" config
Update 2019-10-15: the wp_options.autoload
index is finally added to WordPress Core. Thanks!