WordPress 在查询 post 列表时,默认会同时把文章数量也查询出来,使用这种方式的有:get_posts、query_posts 和 WP_Query。
「WordPress 百万级优化 SQL_CALC_FOUND_ROWS 数据库慢查询解决方案:https://0xo.net/1998」SQL_CALC_FOUND_ROWS 简介
SQL_CALC_FOUND_ROWS 是一个早期 MySql 函数,用于返回一个数据库查询的总行数,以便计算分页所需的页数。问题是,SQL_CALC_FOUND_ROWS 是一个相当古老的函数,没有优化,效率特别低,会拖慢数据库查询。
get_posts 在 WordPress 4.6.1+ 已经不再使用 SQL_CALC_FOUND_ROWS,但是 query_posts 和 WP_Query 还是会用,所以文章数目比较多的话还须优化。
「WordPress 百万级优化 SQL_CALC_FOUND_ROWS 数据库慢查询解决方案:https://0xo.net/1998」具体语句如下:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' ) ORDER BY wp_posts.post_date DESC LIMIT 0, 20
SELECT FOUND_ROWS()
一般在 WordPress 博客网站文章数据量较小时,基本没问题。但是当文章 posts 数量达到 10w+,这个就是一条必现的慢查询,有时候上千文章数量也会偶尔出现。比如首页、分类、标签、搜索页面,只要用到这几个函数,就都会使用 SQL_CALC_FOUND_ROWS。
如何解决 SQL_CALC_FOUND_ROWS 问题优化 WordPress 速度?
禁用掉 SQL_CALC_FOUND_ROWS,用一种更加高效的方式,参考代码如下:
「WordPress 百万级优化 SQL_CALC_FOUND_ROWS 数据库慢查询解决方案:https://0xo.net/1998」//优化数据库慢查询 uxtt.com
if ( ! function_exists( 'theme_set_no_found_rows' ) ){
/**
* 设置 'no_found_rows' 属性为 true,禁用 SQL_CALC_FOUND_ROWS
*/
function theme_set_no_found_rows( \WP_Query $wp_query ) {
$wp_query->set( 'no_found_rows', true );
}
}
add_filter( 'pre_get_posts', 'theme_set_no_found_rows', 10, 1 );
if ( ! function_exists( 'theme_set_found_posts' ) ){
//构建和设置分页
function theme_set_found_posts( $clauses, \WP_Query $wp_query ) {
//单页不处理 uxtt.com
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' ] : '';
// 设置参数、构建并运行查询、结果为 'found_posts'
$wp_query->found_posts = $wpdb->get_var( "SELECT $distinct COUNT(*) FROM {$wpdb->posts} $join WHERE 1=1 $where" );
// 计算每页文章数量
$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' ) ) );
// 设置 max_num_pages 最大页数
$wp_query->max_num_pages = ceil( $wp_query->found_posts / $posts_per_page );
return $clauses;
}
}
add_filter( 'posts_clauses', 'theme_set_found_posts', 10, 2 );
代码复制粘贴到主题 functions.php 文件保存生效即可。有需要不妨试试。
参考资料
WordPress 10w+数据时, 解决 SQL_CALC_FOUND_ROWS 查询使网站变慢问题(文章代码可能导致分页不准确)
解决 SQL_CALC_FOUND_ROWS 数据库慢查询问题的解决方案
「WordPress 百万级优化 SQL_CALC_FOUND_ROWS 数据库慢查询解决方案:https://0xo.net/1998」WordPress: SQL_CALC_FOUND_ROWS, why it’s slow and what to do about it
任何服务、机场均有跑路风险,大小机场也没有绝对好坏,请注意甄别防范!!备用节点参考:大哥云官网、万城专线官网、飞机云官网、搬瓦工JMS、极客云官网……解压及网盘密码 1024