[wp-trac] [WordPress Trac] #17288: slow query in taxonomy.php
WordPress Trac
wp-trac at lists.automattic.com
Sat Apr 30 00:25:19 UTC 2011
#17288: slow query in taxonomy.php
-------------------------+-----------------------------
Reporter: fudj | Owner:
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Taxonomy | Version: 3.1
Severity: normal | Keywords: needs-testing
-------------------------+-----------------------------
platform: ubuntu 10.04
wordpress: 3.1.1
mysql: 5.1.43
mySQL 5.1.43 (which is what I am running) optimises the query incorrectly,
which is particularly slow on my site that has 2000+ posts (40000+ rows in
wp_posts)
OLD QUERY (took 180sec+ to execute)
{{{
SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts WHERE 1=1 AND (
wp_posts.ID IN (
SELECT object_id
FROM wp_term_relationships
WHERE term_taxonomy_id IN
(4594,4600)
GROUP BY object_id HAVING
COUNT(object_id) = 2
) ) AND wp_posts.post_type = 'post' AND
(wp_posts.post_status = 'publish') GROUP BY wp_posts.ID ORDER BY
wp_posts.post_date DESC LIMIT 0, 10;
}}}
NEW QUERY (<1sec)
{{{
SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts WHERE 1=1 AND
EXISTS (
SELECT 1
FROM wp_term_relationships
WHERE term_taxonomy_id IN (4594,4600)
AND object_id = wp_posts.ID
GROUP BY object_id HAVING COUNT(object_id) = 2
) AND wp_posts.post_type = 'post' AND
(wp_posts.post_status = 'publish') GROUP BY wp_posts.ID ORDER BY
wp_posts.post_date DESC LIMIT 0, 10;
}}}
the way to get around it is to change the sub query in taxonomy.php:
LINE 697-702 - replace with:
{{{
$where[] = "EXISTS (
SELECT 1
FROM $wpdb->term_relationships
WHERE term_taxonomy_id IN ($terms)
AND object_id = $primary_table.$primary_id_column
GROUP BY object_id HAVING COUNT(object_id) = $num_terms
)";
}}}
it forces the DB to evaluate inside first.
I'd be interested if this works on other people's servers.
There is a faster version using an inner join, but it changes the
query structure so requires a bit more code editing that I haven't got
around to looking at:
POSSIBLE NEWER BETTER QUERY (requiring more code editing)
{{{
SELECT SQL_CALC_FOUND_ROWS wp_posts.*
FROM wp_posts
INNER JOIN (
SELECT object_id
FROM wp_term_relationships
WHERE term_taxonomy_id IN (4594,4600)
GROUP BY object_id
HAVING COUNT(object_id) = 2
) as term ON term.object_id = wp_posts.ID
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish')
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC LIMIT 0, 10;
}}}
This one gets rid of the looping that occurs in the previous queries
--
Ticket URL: <http://core.trac.wordpress.org/ticket/17288>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software
More information about the wp-trac
mailing list