应客户需求优化WordPres内置搜索功能的性能,客户网站使用了大量搜索页面作为展示,当访问高峰期时产生大量的慢查询,导致网站访问缓慢出现大量502错误。网站为交互类站点,几乎排除了缓存插件的使用;
既然是慢查询那么我们就从数据库和查询语句着手处理,客户的要求是搜索的时候必须匹配标题和内容。所以网上大量的只搜索标题的方法无效。
解决思路:使用Mysql5.7+版本的全文索引+中文分词功能(这里注意:需要5.76+的Mysql数据库版本,才支持中文分词),建立索引后,优化WordPress搜索查询语句;
第一步:安装Mysql5.7+版本,我们这里直接安装了Mysql8.0版本,并添加如下配置到my.ini。
1 2 3 4 |
在 [mysqld]的下面追加: ft_min_word_len = 4 innodb_ft_min_token_size = 3 ngram_token_size = 2 |
添加完成后重启数据库。
第二步:导入数据库,并设置索引。
建议全文索引并指定使用ngram
作为中文分词引擎;示例语句如下:
1 |
ALTER TABLE `wp_posts` ADD FULLTEXT( `post_title`, `post_content` ) WITH PARSER ngram; |
如果之前就设置了标题和内容的全文索引需要删除重建,以指定分词引擎。
Ps: 如果数据库体量较大建立索引需要一点时间
第三步:优化WordPress搜索Sql语句,使用match([col]) against([key])替换原有like语句方案使用。
将以下代码添加到主题functions.php内
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/** * 替换默认搜索查询语句 */ add_filter('posts_search', function ($search, $wp_query) { global $wpdb; if (empty($search)) return $search; $q = $wp_query->query_vars; $n = !empty($q['exact']) ? '' : '%'; $search = $searchand = ''; foreach ((array)$q['search_terms'] as $term) { $term = esc_sql(like_escape($term)); if(mb_strlen($term,'utf8') < 2){ //这里是因为分词机制,导致单个字不能搜索到结果,所以单字搜索搜索标题 $search .= "{$searchand} ($wpdb->posts.post_title LIKE '{$n}{$term}{$n}')"; }else{ $search .= "{$searchand} match($wpdb->posts.post_title,$wpdb->posts.post_content) against('$term' IN BOOLEAN MODE) "; } $searchand = ' AND '; } if (!empty($search)) { $search = " AND ({$search}) "; if (!is_user_logged_in()) $search .= " AND ($wpdb->posts.post_password = '') "; } return $search; }, 10, 2); |
PS: 注意match后面的字段名需要和建立索引时的字段对应上,否则无法使用索引。
更多阅读资料:http://www.chenqiong.net/article/26