[wp-trac] [WordPress Trac] #7599: Inefficient query generation in query_posts [With Suggested Patch]

WordPress Trac wp-trac at lists.automattic.com
Tue Aug 26 16:11:23 GMT 2008


#7599: Inefficient query generation in query_posts [With Suggested Patch]
---------------------+------------------------------------------------------
 Reporter:  pedrop   |       Owner:  pedrop
     Type:  defect   |      Status:  new   
 Priority:  normal   |   Milestone:  2.7   
Component:  General  |     Version:        
 Severity:  normal   |    Keywords:        
---------------------+------------------------------------------------------
 Hi,

 It appears that the wp_query->get_posts function (also called by
 query_posts and used to generate the main loop) isn't building a very
 efficient query when the "category__not_in" parameter is used. What the
 current code does (see below) is first query for a list of posts that have
 that category and then include an array with the id's of the posts into
 the actual query:

 {{{

 if ( !empty($q['category__not_in']) ) {
                         $ids = get_objects_in_term($q['category__not_in'],
 'category');
                         if ( is_wp_error( $ids ) )
                                 return $ids;
                         if ( is_array($ids) && count($ids > 0) ) {
                                 $out_posts = "'" . implode("', '", $ids) .
 "'";
                                 $whichcat .= " AND $wpdb->posts.ID NOT IN
 ($out_posts)";
                         }
                 }
 }}}


 This may work ok for a small amount of posts, but when the database has
 10,000+ posts and most of them aren't in that category it is extremely
 slow.

 An improved version could either use a left join or create a sub query
 such as:

 ...where id not in (select object_id from wp_term_relationships where
 term_taxonomy_id in (8,12) )...

 Where the 8 and the 12 are categories that should be excluded.

 This has proven to be dramatically faster on a large database.

 Here is a proposed patch to be applied to the file "wp-includes/query.php"
 at line 1042 of wordpress 2.6.1. Entire if statement at that line (which
 is the one pasted above) should be replaced with the if statement below:


 {{{
 if ( !empty($q['category__not_in']) ) {
                         $cat_string= "'" . implode("', '",
 $q['category__not_in']) . "'";
                         $whichcat .= " AND $wpdb->posts.ID NOT IN (select
 $wpdb->term_relationships.object_id from $wpdb->term_relationships where
 $wpdb->term_relationships.term_taxonomy_id in ($cat_string) )";
                 }
 }}}

-- 
Ticket URL: <http://trac.wordpress.org/ticket/7599>
WordPress Trac <http://trac.wordpress.org/>
WordPress blogging software


More information about the wp-trac mailing list