wordpress支撑百万文章解决方案

技术 作者:有料 2020-02-05 10:09:18
无论是从功能方面还是开发方面,wordpress用起来都很便利,但便利的背后是以牺牲明能为代价的。最近想着优化一下wordpress,看看有没有什么方案能够将wordpress支撑起百万的数据呢。 支撑百万数据并不是存入一百万文章就可以了,实际上百万文章对mysql来说毫无压力,别说百万了,上亿也没什么关系,有关系的是查询。很不幸,如果主题写的不好,百万文章的wordpress查询就是个灾难。

从首页开始看

一般来说,达到百万文章级别的站点,首页应该是一个展示很多分类文章的页面。但是由于wp在初始化的时候就会根据url中的查询去数据库查询一些文章,首页是根据时间倒序查询,因此当不需要最新文章的时候,可以利用钩子去掉这部分查询。当需要最新文章的时候,也需要优化这个查询,默认的查询是带有SQL_CALC_FOUND_ROWS,这个简直是性能杀手!
当需要从分类取出一些数据的时候,使用WP_Query构造出的查询也会用到filesort,因此可以选择构建一张表,作为中间查询。

文章页面

看看文章页面,似乎没有什么费时间的查询,基本上就是id查询内容,用到了索引,但是其中有一个翻页的问题,其中有一个翻页的功能是可以筛选出相同分类的上下篇文章,这种查询的sql语句如下
mysql> SELECT p.ID FROM wp_posts AS p
  
INNER JOIN wp_term_relationships AS tr ON p.ID = tr.object_id INNER JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE p.post_date > '2017-07-04 09:57:50' AND p.post_type = 'post' AND tt.taxonomy = 'category' AND tt.term_id IN (4) AND p.post_status = 'publish' ORDER BY p.post_date ASC LIMIT 1;
使用explain看看
mysql> explain SELECT p.ID FROM wp_posts AS p INNER JOIN wp_term_relationships AS tr ON p.ID = tr.object_id INNER JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE p.post_date > '2017-07-04 09:57:50' AND p.post_type = 'post' AND tt.taxonomy = 'category' AND tt.term_id IN (4) AND p.post_status = 'publish' ORDER BY p.post_date ASC LIMIT 1\G
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: tt
 type: const
 possible_keys: PRIMARY,term_id_taxonomy,taxonomy
 key: term_id_taxonomy
 key_len: 106
 ref: const,const
 rows: 1
 Extra: Using temporary; Using filesort
 *************************** 2. row ***************************
 id: 1
 select_type: SIMPLE
 table: tr
 type: ref
 possible_keys: PRIMARY,term_taxonomy_id
 key: term_taxonomy_id
 key_len: 8
 ref: const
 rows: 5576
 Extra:
 *************************** 3. row ***************************
 id: 1
 select_type: SIMPLE
 table: p
 type: eq_ref
 possible_keys: PRIMARY,type_status_date
 key: PRIMARY
 key_len: 8
 ref: aikanwen.tr.object_id
 rows: 1
 Extra: Using where
 3 rows in set (0.19 sec)
看起来就是个灾难现场,这种查询会随着分类的增加而变得奇慢无比,因为有时候分类和标签可能会达到几万几十万个!

分类页面

同首页。

插件

wordpress最常用的插件可能是wp_postviews了,但是对于百万文章的wordpress来说,这个插件可能是个灾难,如果你用到了它的排行榜的话。 这个排行榜会使用一个如下的查询
SELECT wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND ( 
 wp_postmeta.meta_key = 'views'
) AND wp_posts.post_type IN ('post', 'page', 'attachment') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value+0 DESC LIMIT 0, 10;
这种查询也是一个灾难,对于wp来说,wp_post_meta表中根本没有meta_key 和 meta_value的索引,也是根本无法使用索引做排序,所以只能使用filesort,需要全表扫描。可以看看explain。
mysql> explain SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id ) WHERE 1=1 AND ( wp_postmeta.meta_key = 'views' ) AND wp_posts.post_type IN ('post', 'page', 'attachment') AND (wp_posts.post_status = 'publish' OR wp_posts.post_author = 1 AND wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_postmeta.meta_value+0 DESC LIMIT 0, 10 \G;
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: wp_postmeta
 type: ALL
 possible_keys: post_id,meta_key
 key: NULL
 key_len: NULL
 ref: NULL
 rows: 67053
 Extra: Using where; Using temporary; Using filesort
 *************************** 2. row ***************************
 id: 1
 select_type: SIMPLE
 table: wp_posts
 type: eq_ref
 possible_keys: PRIMARY,type_status_date,post_author
 key: PRIMARY
 key_len: 8
 ref: aikanwen.wp_postmeta.post_id
 rows: 1
 Extra: Using where
 2 rows in set (0.17 sec)
这种排序一次,基本就是个灾难。别说百万,十万文章蜘蛛都能搞挂了。 … 最后我放弃优化了,还是重新构建一个能过支撑百万级别的数据库结构比较简单。wordpress本身定位就是博客,放太多的数据查询起来太慢了。 来自:http://imhuchao.com/1095.html

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接