通过执行计划explain分析如下查询语句
- mysql> explain select msg_id from circlemessage_idx_0 where to_id = 113487 and circle_id=10019063 and msg_id>=6273803462253938690 and from_id != 113487 order by msg_id asc limit 30;
- +----+-------------+---------------------+-------+-------------------------+---------+---------+------+--------+-------------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
- +----+-------------+---------------------+-------+-------------------------+---------+---------+------+--------+-------------+
- | 1 | SIMPLE | circlemessage_idx_0 | range | PRIMARY,idx_from_circle | PRIMARY | 16 | NULL | 349780 | Using where |
- +----+-------------+---------------------+-------+-------------------------+---------+---------+------+--------+-------------+
- 1 row in set (0.00 sec)
-
-
- mysql> explain select msg_id from circlemessage_idx_0 where to_id = 113487 and circle_id=10019063 and from_id != 113487 order by msg_id asc limit 30;
- +----+-------------+---------------------+-------+-----------------+---------+---------+------+------+-------------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
- +----+-------------+---------------------+-------+-----------------+---------+---------+------+------+-------------+
- | 1 | SIMPLE | circlemessage_idx_0 | index | idx_from_circle | PRIMARY | 16 | NULL | 30 | Using where |
- +----+-------------+---------------------+-------+-----------------+---------+---------+------+------+-------------+
- 1 row in set (0.00 sec)
问题分析
通过上面两个执行计划可以发现当没有msg_id >= xxx这个查询条件的时候,检索的rows要少很多,并且两者查询的时候都用到了索引,而且用到的还只是主键索引。那说明索引应该是不合理的,没有发挥最大作用。
分析这个执行计划可以看到,当包含msg_id >= xxx 查询条件的时候,rows有34w多行,这种情况,说明检索太多,要么就是表里面确实有这么大,要么就是索引不合理没有用到索引,大都情况是没用合理用到索引。
列中所用到的索引也是PRIMARY,那就可能是(msg_id,to_id)的其中一个,注意我们建立表的时候msg_id索引的顺序是在to_id前面的,因此MySQL查询一定会优先用msg_id索引,在使用了msg_id索引后,就已经检索出了34w行,并且由于msg_id的查询条件是大于等于,因此,再这个查询条件后,就不能再用到to_id的索引。
然后再看key_len长度为16,结合 key为PRIMARY,那么可以分析得知,只有一个主键索引被用到。
最后看看 type 值,是range,那么就说明这个查询要么是范围查询,要么就是多值匹配。
请注意,from_id != xxx这样的语句,是无法用到索引的。只有from_id = xxx就可以用到所以,因此from id 的索引其实可以不用,建立索引的时候就要考虑清楚
如何优化
既然知道索引不合理,那么就要分析并调整索引。一般而言,我们既然要从单表里面查询,那么就需要能够知道大体,单表里面大致会有哪些数据,现在的量级大概是多少。
然后开始下一步的分析,既然msgid是被设置为了主键,那一定是全局唯一的,所有,有多少数据量就至少会有多少条msgid;那么检索msg_id基本就是检索整个表了。
我们要做的优化就是要尽量减少索引,减少查询的行数;那么就需要思考,通过查询哪些字段才能够减少行数?比如,一个张表里面,所属某个用户的数据,会不会比查询msgid的行数要少?查询某个用户并且是属于某个圈子的,那会不会就更少了?等等。
然后根据实际情况分析,单表里面命中to_id 的行数应该是会小于命中msg_id的,因此要首先保证能够使用到to_id的索引
为此,可以设置主键的时候把msg_id和to_id的顺序交互一下;但是,由于已经是线上的表,已经有了大量数据,并且业务开始运行,这种情况下,修改主键会引发很多问题(当然修改索引是OK的),因此,不建议直接修改主键。
那么,为了保证有效使用to_id的索引,就要新建一个联合索引;那么新建的联合索引的第一索引字段必然是to_id
(编辑:威海站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|