[wp-trac] [WordPress Trac] #33885: meta_form performs a potentially expensive query

WordPress Trac noreply at wordpress.org
Thu May 25 10:29:33 UTC 2017

#33885: meta_form performs a potentially expensive query
 Reporter:  jorbin                   |       Owner:
     Type:  defect (bug)             |      Status:  new
 Priority:  normal                   |   Milestone:  Future Release
Component:  Administration           |     Version:  4.3.1
 Severity:  critical                 |  Resolution:
 Keywords:  has-patch needs-testing  |     Focuses:  performance

Comment (by johnjamesjacoby):

 Looking at this more, we are lucky that ordering by `meta_key` is not very
 popular. This appears to be the only place in core where that happens, and
 none of the more popular plugins have do this either.

 In addition, `WP_Meta_Query` does not support ordering by `meta_key` – any
 attempts to do so are ignored.


 The simplest option is @pento's original patch. Removing the `ORDER BY`
 clause (or using `ORDER BY NULL`) prevents MySQL from `Using filesort` on
 the result set, which does result in an overall performance improvement.

 Unfortunately, it isn't until the `VARCHAR` length matches the `meta_key`
 index length that `Using temporary` stops and the `meta_key` index is
 fully utilized.


 As far as directly altering `_postmeta` in concerned:

 ALTER TABLE wp_postmeta MODIFY meta_key varchar(191);

 I'd like to caution against doing this for a few reasons:

 * Doing this only to `_postmeta` and not the other meta-data tables goes
 against the normalization of the meta API. It's a change you will quickly
 forget you made here, and will inevitably cause a problem years from now
 in your application.
 * You'll want to run `ANALYZE TABLE wp_postmeta;` afterwards, or visit
 `/wp-admin/maint/repair.php` and follow the on-screen instructions. This
 is because `ALTER`ing the database table alone does not rebuild the key
 * On tables with millions of rows, both the `ALTER` and the above `ANALYZE
 TABLE` queries will take several seconds (or minutes) to complete.
 * On installations with replication, you will want to monitor your
 secondaries, making sure their key distributions match the primary.
 * Running this `ALTER` has the hidden consequence of also updating the
 `meta_key` index to assume the length of the `meta_key` column, so future
 `ALTER`s on this column will directly effect the index too.
 KEY `meta_key` (`meta_key`(191))
 // Becomes:
 KEY `meta_key` (`meta_key`)
 // Because column & key share the same length, the key length definition
 is dropped


 My conclusions:

 * Future versions of MySQL and MariaDB will default to
 `innodb_large_prefix` [https://mariadb.com/kb/en/mariadb/xtradbinnodb-
 server-system-variables/#innodb_large_prefix being `ON` by default]. This
 won't directly avoid temporary tables & filesorts, but it will generally
 improve query performance the way @matt_fw eluded to earlier.
 * For anyone that has added an index to their `meta_value` columns (not
 uncommon for sites that do complex `JOIN`s), you'll want to keep a similar
 eye on your customizations.
 * Because of how rare & weird it is to `ORDER BY meta_key`, I do think
 it's OK to not optimize the meta database tables for his behavior.
 * I do not think it's OK for our meta database tables to all have an
 ineffective `meta_key` index. Thankfully, even when their lengths are
 misaligned, the `meta_key` index does still function as intended for all
 queries other than `ORDER BY meta_key`.
 * @dd32's transient approach in
 [https://core.trac.wordpress.org/ticket/33885#comment:44 #44] is a sound
 work-around for this isolated problem, for now.
 * For later, we should consider what a redux of this meta-box experience
 looks like.
 * Like we have `wp_is_large_network()`, we could consider a
 `wp_is_large_site()` companion. In theory, it could be used by plugins
 like WooCommerce or bbPress to announce to the rest of the environment
 "hey, maybe the posts table will have more rows than is considered
 typical" so other aspects of the system can respond accordingly.

Ticket URL: <https://core.trac.wordpress.org/ticket/33885#comment:47>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform

More information about the wp-trac mailing list