WordPress教程

WordPress多种分类法混合查询优化方案

阿里云

我们在使用 wordpress 建站,特别是一些 CMS 类型的站点,多种分类法是常用的,然而 WordPress 在使用多种分类法混合查询的时候,这个查询语句就复杂了,在分类和文章数量多了之后,速度就堪忧了,所以这里提一种优化方案供参考。

举例:某个案例中,对于默认的除了的 category 和 post_tag,新增了一个名为 kind 的分类法,注册新分类法的步骤这里就不赘述了,然后我们需要查询出同时归属于 categoryID 为 1,kind 的 ID 为 2 的文章,普通的做法:

也想出现在这里?联系我们
创客主机
  1. $args = array( 
  2.   'post_type'=>'post',
  3.   'tax_query'=>array(
  4.     'relation'=>'AND',
  5.     array(
  6.       'taxonomy'=>'category',
  7.       'field'=>'term_id',
  8.       'operator'=>'IN',
  9.       'terms'=>array(1)
  10.     ),
  11.     array(
  12.       'taxonomy'=>'kind',
  13.       'field'=>'term_id',
  14.       'operator'=>'IN',
  15.       'terms'=>array(2),
  16.     )
  17.   )
  18. );
  19. query_posts($args);

就上面这个查询来说,在没有缓存的情况下要执行 3 次数据库查询,前面两次分别查询对应的分类是否存在,重点是第 3 次文章查询,由于 wordpress 分类和文章的对应关系存储 wp_term_relationships 表中,每篇文章对应每一个分类都有一条记录,所以查询文章的时候主要要两次 left join 这个 wp_term_relationships 表,一旦数据量多起来,这样的查询就比较慢了,附打印出的查询语句如下。

  1. SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID FROM wp_posts  LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)  LEFT JOIN wp_term_relationships AS tt1 ON (wp_posts.ID = tt1.object_id) WHERE 1=1  AND ( 
  2.   wp_term_relationships.term_taxonomy_id IN (1) 
  3.   AND 
  4.   tt1.term_taxonomy_id IN (2)
  5. ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 10

我的解决方案,在 wp_posts 表中增加一个字段,用来存储器中的一个分类的信息,比如这个案例里面我把 kind 的 ID 信息冗余存储在 wp_posts 表中,然后将查询条件放到 wp_posts 表中,这样就能提速了。

第一步:在启用主题的时候,执行 sql 在 wp_posts 表中增加 kind_id 字段,并加上 Index 索引。(在这个案例中因为客户的分类可以确定是单选,所以 kind_id 字段的类型就直接用 int 了,如果你要保存多个分类 ID,可以改为 varchar 类型,不过 varchar 类型就不别弄索引了)。

  1. //激活主题时执行
  2. function ashu_add_pages() {
  3.   global $pagenow;
  4.   if ( 'themes.php' == $pagenow && isset( $_GET['activated'] ) ){
  5.     ashuwp_alter_posts_table();
  6.   }
  7. }
  8. add_action( 'load-themes.php', 'ashu_add_pages' );
  9.  
  10. //修改posts表,增加一列kind_id
  11. function ashuwp_alter_posts_table(){
  12.   global $wpdb;
  13.  
  14.   //判断字段是否已经存在
  15.   $sql1 = "Describe {$wpdb->posts} `kind_id`";
  16.   $kind_id_exist = $wpdb->query($sql1);
  17.  
  18.   if( !$kind_id_exist ){
  19.     //新增列
  20.     $add_column = "ALTER TABLE {$wpdb->posts} ADD COLUMN `kind_id` INT(10) DEFAULT NULL";
  21.     $wpdb->query($add_column);
  22.  
  23.     //添加索引
  24.     $add_index = "ALTER TABLE {$wpdb->posts} ADD INDEX kind_id (`kind_id`)";
  25.     $wpdb->query($add_index);
  26.  
  27.   }
  28.  
  29. }

第二步:发布文章的时候,将 kind 分类的 ID 信息保存到 wp_posts 表中的 kind_id 字段。这里使用 set_object_terms 钩子,就是在设置分类的时候用,当然为了避免后台多选,这里只保存一个 ID 数据

  1. add_action( 'set_object_terms', 'ashuwp_add_post_kind_id', 10, 6);
  2. function ashuwp_add_post_kind_id( $object_id, $terms, $tt_ids, $taxonomy, $append = false, $old_tt_ids = array() ){
  3.  
  4.   global $wpdb;
  5.   if( $taxonomy=='kind' ){
  6.     $term_id = reset( $tt_ids );
  7.     if( $term_id ){
  8.       $sql = "UPDATE {$wpdb->posts} SET `kind_id`={$term_id}  where `ID`={$object_id}";
  9.       $wpdb->get_results( $sql );
  10.     }
  11.   }
  12.  
  13. }

第三步:我希望在使用 WP_Query 查询文章时直接传入 kind_id 参数即可,所以使用 posts_where 钩子,检测是否有 kind_id 参数,然后拼接查询语句。

  1. function ashuwp_query_posts_where( $where, $query){
  2.   global $wpdb;
  3.  
  4.   $qv = $query->query_vars;
  5.  
  6.   isset( $qv['kind_id'] ) AND $kind_id = absint($qv['kind_id']) AND $where .= " AND {$wpdb->posts}.kind_id = {$kind_id}";
  7.  
  8.   return $where;
  9.  
  10. }
  11. add_filter( 'posts_where', 'ashuwp_query_posts_where', 10, 2);

第四步:查询文章。最开始那一段查询可以直接改成如下代码即可。

  1. $args = array( 
  2.   'post_type'=>'post',
  3.   'kind_id'=>2, //直接使用kind_id做参数
  4.   'tax_query'=>array(
  5.     array(
  6.       'taxonomy'=>'category',
  7.       'field'=>'term_id',
  8.       'operator'=>'IN',
  9.       'terms'=>array(1)
  10.     )
  11.   )
  12. );
  13. query_posts($args);

好了,就到这里,这里在下只是提供了一种 WordPress 的查询优化方案,可用此方案自行改造其他应用。

WordPress 多种分类法混合查询优化方案

已有 302 人购买
查看演示升级 VIP立刻购买

收藏
(0)

发表回复

热销模板

Ashade - 作品展示摄影相册WordPress汉化主题
LensNews

本站承接 WordPress / PbootCMS / DedeCMS 等
系统建站、仿站、开发、定制等业务!