[wp-trac] [WordPress Trac] #18536: Improve performance of WP_Query core

WordPress Trac wp-trac at lists.automattic.com
Mon Dec 19 15:17:26 UTC 2011


#18536: Improve performance of WP_Query core
-----------------------------+--------------------
 Reporter:  cheald           |       Owner:
     Type:  enhancement      |      Status:  new
 Priority:  normal           |   Milestone:  3.4
Component:  Performance      |     Version:  3.2.1
 Severity:  normal           |  Resolution:
 Keywords:  has-patch early  |
-----------------------------+--------------------

Old description:

> WP_Query, by default, selects wp_posts.* when building post queries. This
> can result in extremely large result sets when used with a large wp_posts
> table, resulting in MySQL being forced to use a temp table for sorting,
> which leads to all sorts of performance problems. SELECT * is generally
> considered to be a code smell as is, and is commonly known to cause
> problems at scale.
>
> This patch breaks default WP_Query queries into two parts - one to select
> a list of IDs with the given selection criteria, and a second to actually
> select the posts once the IDs have been determined. This vastly reduces
> the amount of data that has to be processed by the database, resulting in
> fewer context switches and vastly improved performance.
>
> I have implemented this in a production system with a wp_posts table with
> over 450k rows and reduced query times by two orders of magnitude.
> Database CPU burn is down by 90% and context switches have been
> drastically reduced.
>
> This is anecdotal, of course, but here's what this patch did for our DB
> master:
>
> [[Image(http://cl.ly/2j3a2a161m2131351j1w/Image_2011-08-27_at_9.15.23_PM.png)]]
>
> This should be of some benefit even in small cases, since smaller
> datasets will result in faster sorts. The overhead of the second query is
> minimal. In large cases, the performance benefits range from "good" to
> "dramatic".
>
> I have run the Wordpress PHPUnit test suite against the patch, and it did
> not break any tests. The suite, when I checked it out, had multiple
> failures present, but no new ones were introduced by this change.

New description:

 WP_Query, by default, selects wp_posts.* when building post queries. This
 can result in extremely large result sets when used with a large wp_posts
 table, resulting in MySQL being forced to use a temp table for sorting,
 which leads to all sorts of performance problems. SELECT * is generally
 considered to be a code smell as is, and is commonly known to cause
 problems at scale.

 This patch breaks default WP_Query queries into two parts - one to select
 a list of IDs with the given selection criteria, and a second to actually
 select the posts once the IDs have been determined. This vastly reduces
 the amount of data that has to be processed by the database, resulting in
 fewer context switches and vastly improved performance.

 I have implemented this in a production system with a wp_posts table with
 over 450k rows and reduced query times by two orders of magnitude.
 Database CPU burn is down by 90% and context switches have been
 drastically reduced.

 This should be of some benefit even in small cases, since smaller datasets
 will result in faster sorts. The overhead of the second query is minimal.
 In large cases, the performance benefits range from "good" to "dramatic".

 I have run the Wordpress PHPUnit test suite against the patch, and it did
 not break any tests. The suite, when I checked it out, had multiple
 failures present, but no new ones were introduced by this change.

--

Comment (by nacin):

 Removing the screenshot (dead link). I do remember the graph looking
 mighty impressive, though.

-- 
Ticket URL: <http://core.trac.wordpress.org/ticket/18536#comment:19>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software


More information about the wp-trac mailing list