写在前面:Discuz!作为首屈一指的社区
系统,为大多数站长提供了一站式
网站解决方案,而且是
开源的(虽然部分代码是加密的)。它对垂直行业的发展做出了巨大的贡献。尽管如此,Discuz!系统的源代码,还或多或少有点坑。最著名的是
默认的MyISAM引擎,并基于会话引擎MyISAM建筑
功能。会话表使用的存储引擎。这一次我们要谈Discuz!
处理热门文章的逻辑功能的另一个问题。
在我们的环境中,使用的mysql-5.6.6版。
在查看一个帖子和一个页面的过程中,会有一个SQL,如下所示:
MySQL > DESC SELECT * FROM pre_forum_post哪里
8201301、` TID =无形中`('0',' 2 ')通过日界线DESC LIMIT 15 G阶
*************************** 1。行***************************
编号:1
select_type:简单
表:pre_forum_post
类型:裁判
possible_keys:tid,
显示顺序,第一
关键:显示顺序
key_len:3
参考:const
行数:593371
额外的:索引的使用
条件;使用;使用filesort
SQL
执行的成本是:
-索引访问的行数通常是更好的状态。
| handler_read_key | 16 |
根据索引序列访问下一行的次数通常是由于索引的范围扫描或全索引扫描,通常是一个良好的状态。
| handler_read_next | 329881 |
-行记录的总数是按一定顺序读取的。如果需要对结果
排序,则值通常较大。当无法对全表扫描或多表联接进行索引时,该值也会更大。
| handler_read_rnd | 15 |
当爱需要回头很多页的时候,比如:
MySQL > DESC SELECT * FROM pre_forum_post哪里
8201301、` TID =无形中`('0',' 2 ')的
日期限129860, 15 G阶
*************************** 1。行***************************
编号:1
select_type:简单
表:pre_forum_post
类型:裁判
possible_keys:显示顺序
关键:显示顺序
key_len:3
参考:const
行数:593371
额外的:使用;使用filesort
的SQL执行的成本已成为(比handler_read_key和handler_read_rnd大很多):
| handler_read_key | 129876 | --因为跳过了很多前排
| handler_read_next | | - 329881。
| handler_read_rnd | 129875 | --因为需要排序的结果集的第一大
显然,当SQL遇到热点时,价格会非常高,如果访问历史记录的响应量太大,或者
搜索引擎已经重复请求并回复历史页面,那么很容易直接破坏数据库
服务器。
总结:这个SQL不能使用`显示顺序`指数第二列的`无形`指数(范围),导致无法完成对`使用综合指数的日期`领域需求排序的范围
查询(如果在TID =和无形的(日期,和)=本案可以用于组合索引,注意下两者的不同)。
知道这个
原因,相应的
优化解决方案是明确的:
创建一个新的索引idx_tid_dateline,仅包含两列TID和日界线。(根据其他指标,统计信息的item_type和item_id基数太低,所以它不包括在欧盟指标。当然,你也可以一起想想。
让我们看一下新索引之后的执行计划:
MySQL > DESC SELECT * FROM pre_forum_post哪里
8201301、` TID =无形中`('0',' 2 ')的日期限15 G阶
*************************** 1。行***************************
编号:1
select_type:简单
表:pre_forum_post
类型:裁判
possible_keys:tid,显示顺序,首先,idx_tid_dateline
关键词:idx_tid_dateline
key_len:3
参考:const
行数:703892
附加:使用在哪里
你可以看到,以前使用filesort正在消失,和排序可以直接通过指数。
但是,如果把爱情转到旧的历史来回复,相应的SQL仍然不能使用新的索引:
MySQL > DESC SELECT * FROM pre_forum_post哪里
8201301、` TID =无形中`('0',' 2 ')的日期限制129860,15 G阶
*************************** 1。行***************************
编号:1
select_type:简单
表:pre_forum_post
类型:裁判
possible_keys:tid,显示顺序,首先,idx_tid_dateline
关键:显示顺序
key_len:3
参考:const
行数:593371
额外的:使用;使用filesort
与此相反,如果建议优化器使用新索引,执行计划是什么:
MySQL > DESC SELECT * FROM pre_forum_post利用指数(idx_tid_dateline)的地方
8201301、` TID =无形中`('0',' 2 ')的日期限制129860,15 G阶
*************************** 1。行***************************
编号:1
select_type:简单
表:pre_forum_post
类型:裁判
possible_keys:idx_tid_dateline
关键词:idx_tid_dateline
key_len:3
参考:const
行数:703892
附加:使用在哪里
正如您所看到的,因为查询优化器认为后者需要扫描的行数比前者多11万以上,因此前者效率更高。
事实上,在这种
情况下,分选成本较高,所以我们需要优先排序。因此,我们应该强制使用新的索引,即使用后执行计划在相应
程序中指定索引。
最后,我们看一下爱情转向非常古老的历史来回答,两个执行计划分别分析统计信息的比较:
1。使用旧的指数(显示顺序):
MySQL >选择*从pre_forum_post哪里
8201301、` TID =无形中`('0',' 2 ')的限制129860,15订单日期;
#查看分析结果
|开始| 0.020203 |
|
检查权限| 0.000026 |
表0.000036 | | |开放
| init | 0.000099 |
|系统锁| 0.000092 |
|优化| 0.000038 |
|统计| 0.000123 |
|准备| 0.000043 |
|排序结果| 0.000025 |
|执行| 0.000023 |
|发送数据| 0.000045 |
|创建排序索引| 0.941434 |
|端| 0.000077 |
|查询结束| 0.000044 |
|
关闭表| 0.000038 |
|释放项目| 0.000056 |
|
清理| 0.000040 |
2。如果这是一个新的指标(idx_tid_dateline):
MySQL >选择*从pre_forum_post利用指数(idx_tid_dateline)的地方
8201301、` TID =无形中`('0',' 2 ')的限制129860,15订单日期;
#对比观察分析结果
|开始| 0.000151 |
|检查权限| 0.000033 |
表0.000040 | | |开放
| init | 0.000105 |
|系统锁| 0.000044 |
|优化| 0.000038 |
|统计| 0.000188 |
|准备| 0.000044 |
|排序结果| 0.000024 |
|执行| 0.000023 |
|发送数据| 0.917035 |
|端| 0.000074 |
|查询结束| 0.000030 |
|关闭表| 0.000036 |
|释放项目| 0.000049 |
|清理| 0.000032 |
可以看出,效率提高了,但不是很明显,因为我们真正需要扫描的数据量比较大,所以发送数据阶段需要更多的时间。
此时,我们可以参考前面的优化之一:MySQL优化案例系列-分页优化
然后,您可以将SQL改写成以下内容:
MySQL >解释选择*从pre_forum_post T1内
连接(
选择ID从pre_forum_post利用指数(idx_tid_dateline)的地方
8201301、` TID =无形中`('0','2')以
日期限制129860,15)T2
使用(id)
*************************** 1。行***************************
编号:1
select_type:初级
表:
类型:所有
possible_keys:空
关键词:零
key_len:空
参考:空
行数:129875
额外的:空
*************************** 2。行***************************
编号:1
select_type:初级
表:T1
类型:eq_ref
possible_keys:初级
关键词:小学
key_len:4
参考:t2.id
行数:1
额外的:空
*************************** 3。行***************************
编号:2
select_type:衍生
表:pre_forum_post
类型:裁判
possible_keys:idx_tid_dateline
关键词:idx_tid_dateline
key_len:3
参考:const
行数:703892
附加:使用在哪里
查看SQL的剖析统计数据。
|开始| 0.000209 |
|检查权限| 0.000026 |
|检查权限| 0.000026 |
表0.000101 | | |开放
| init | 0.000062 |
|系统锁| 0.000049 |
|优化| 0.000025 |
|优化| 0.000037 |
|统计| 0.000106 |
|准备| 0.000059 |
|排序结果| 0.000039 |
|统计| 0.000048 |
|准备| 0.000032 |
|执行| 0.000036 |
|发送数据| 0.000045 |
|执行| 0.000023 |
|发送数据| 0.225356 |
|端| 0.000067 |
|查询结束| 0.000028 |
|关闭表| 0.000023 |
|除tmp table | 0.000029 |
|关闭表| 0.000044 |
|释放项目| 0.000048 |
|清理| 0.000037 |
正如你所看到的,它的效率是1倍以上,而且相当不错。
最后,这个问题只会出现在链接页面中,只有1、2页回复的帖子如果是在原来的计划中使用,有什么问题吗。
因此,Discuz!官方要
修改或添加新索引,并确定页面是否链接在代码中,必须使用新的索引,以避免
性能问题。