I’m using the WordPress theme Engine from Industrialthemes and see that the rendering of the front page uses a lot of queries that uses around 0.4 seconds to run in my MySQL database. Like this one:
SELECT SQL_NO_CACHE SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE 1 =1
AND (wp_term_relationships.term_taxonomy_id IN (1))
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'closed')
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 5;
Is there any way this query can be improved? As far as I can see, the WordPress installation have the default indexes in place for all involved fields. My knowledge on tuning SQL Select statements is not good so I’m hoping for some experts to help me on this one. Thanks.
(From Comment)
CREATE TABLE wp_term_relationships (
object_id bigint(20) unsigned NOT NULL DEFAULT '0',
term_taxonomy_id bigint(20) unsigned NOT NULL DEFAULT '0',
term_order int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (object_id,term_taxonomy_id),
KEY term_taxonomy_id (term_taxonomy_id),
KEY idx1 (object_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
(Later…)
CREATE TABLE wp_term_relationships (
object_id bigint(20) unsigned NOT NULL DEFAULT '0',
term_taxonomy_id bigint(20) unsigned NOT NULL DEFAULT '0',
term_order int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (object_id,term_taxonomy_id),
KEY term_taxonomy_id (term_taxonomy_id),
KEY idx1 (term_taxonomy_id,object_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
Both are “covering” indexes.
The former lets the
JOIN
work efficiently and gives the optimizer the option of starting withwp_term_relationships
. And it should replaceKEY term_taxonomy_id (term_taxonomy_id)
.The latter should work well regardless of which table is picked first.
(More)
With this formulation,
If the EXPLAIN starts with p:
If the EXPLAIN starts with tr:
The main problems:
GROUP BY
was adding effort. (I eliminated it by changing theJOIN
to anEXISTS
.)IN ( 'publish', 'closed' )
— inhibits effective use of index.SQL_CALC_FOUND_ROWS
— means that it can’t stop when it gets 5 rows.IN (1)
turn into= 1
, which is fine; butIN (1,2)
is messier.Or, to be more blunt, WP has not yet been engineered to scale.
Please add the indexes and get the
EXPLAIN SELECT
.From pastebin:
This is a different query. It needs this also:
And…
needs
I would add both of those indexes to
tt
and see what happens to theEXPLAINs
and to performance.Rewrite query See if this gives you the ‘right’ answer:
Notes:
GROUP BY
removeda AND b OR c
is equivalent to(a AND b) OR c
, but I think you wanteda AND (b OR c)