WordPress 10w+数据时, 解决SQL_CALC_FOUND_ROWS查询使网站变慢问题
WordPress在查询post列表时,默认会同时把文章数量也查询出来,
使用这种方式的有:get_posts 、query_posts和WP_Query。
get_posts在4.6.1+已经不用SQL_CALC_FOUND_ROWS,但是query_posts和WP_Query还是会用,所以还须优化。
具体语句如下:
SELECTSQL_CALC_FOUND_ROWSwp_posts.IDFROMwp_postsWHERE1=1ANDwp_posts.post_type='post'AND(wp_posts.post_status='publish')ORDERBYwp_posts.post_dateDESCLIMIT0,20 SELECTFOUND_ROWS()
这在网站数据量小的时候,不会引起什么问题,
但是当post数量到10w+的时候,这个就是一条必现的慢查询,
首页、分类、标签、搜索页面,只要用到这几个函数,就都会使用SQL_CALC_FOUND_ROWS这个方式。
那么,如何解决?
禁用掉SQL_CALC_FOUND_ROWS用法,用一种更加高效的方式,
这里我们用EXPLAIN方式,为什么用EXPLAIN而不是count(*)?
具体代码如下,放在functions.php文件:
if(!function_exists('maizi_set_no_found_rows')){ /** *设置WP_Query的'no_found_rows'属性为true,禁用SQL_CALC_FOUND_ROWS * *@paramWP_Query$wp_queryWP_Query实例 *@returnvoid */ functionmaizi_set_no_found_rows(\WP_Query$wp_query) { $wp_query->set('no_found_rows',true); } } add_filter('pre_get_posts','maizi_set_no_found_rows',10,1); if(!function_exists('maizi_set_found_posts')){ /** *使用EXPLAIN方式重构 */ functionmaizi_set_found_posts($clauses,\WP_Query$wp_query) { //Don'tproceedifit'sasingularpage. if($wp_query->is_singular()){ return$clauses; } global$wpdb; $where=isset($clauses['where'])?$clauses['where']:''; $join=isset($clauses['join'])?$clauses['join']:''; $distinct=isset($clauses['distinct'])?$clauses['distinct']:''; $wp_query->found_posts=(int)$wpdb->get_row("EXPLAINSELECT$distinct*FROM{$wpdb->posts}$joinWHERE1=1$where")->rows; $posts_per_page=(!empty($wp_query->query_vars['posts_per_page'])?absint($wp_query->query_vars['posts_per_page']):absint(get_option('posts_per_page'))); $wp_query->max_num_pages=ceil($wp_query->found_posts/$posts_per_page); return$clauses; } } add_filter('posts_clauses','maizi_set_found_posts',10,2);
参考资料:
- WordPress:SQL_CALC_FOUND_ROWS,whyit’sslowandwhattodoaboutit
- SpeedupWordPressWP_Queryandquery_postsfunctions