mysql的where、order by和limit的隐藏优化

一、环境准备

mysql InnoDB有下面两个表:

viewing_number(1814483行数据)
列:id、content_id、sel_count、create_time、update_time

viewing_number_copy(1814483行数据)
列:id、content_id、sel_count、create_time、update_time
索引: update_time

二、观察与分析(第一组,没有索引)

观察

explain select id,update_time from viewing_number v where update_time>="2020-05-27 06:30:55" order by id;
在这里插入图片描述

explain select id,update_time from viewing_number v where update_time>="2020-05-27 06:30:55" order by id limit 100;
在这里插入图片描述

explain select id,update_time from viewing_number v where update_time>="2020-05-27 06:30:55" order by id limit 10000;
在这里插入图片描述

分析

可以发现3次执行计划是一样的,都是用到了主键索引,并且是在where里用的。但是where条件里并没有用到主键……,而是order by用到了。这是什么原理?

这里mysql有个优化:

  1. 如果where没有用到索引,order by也没有用到索引
    先执行where,全表扫描找出符合条件的行,再按照order by在内存中进行排序。
  2. 如果where没有用到索引,但是order by用到索引了
    先执行order by,扫描用到的索引,再回表判断where是否符合条件。
  3. 如果在2的情况下,有limit
    则取够limit条符合条件的行就返回了,并不会扫描完所有索引。

三、观察与分析(第二组,有索引)

观察

explain select id,update_time from viewing_number_copy v where update_time>="2020-05-27 06:30:55" order by id;
在这里插入图片描述

explain select id,update_time from viewing_number_copy v where update_time>="2020-05-27 06:30:55" order by id limit 100;
在这里插入图片描述

explain select id,update_time from viewing_number_copy v where update_time>="2020-05-27 06:30:55" order by id limit 10000;
在这里插入图片描述

分析

可以发现1,3次执行计划是一样的,2的执行计划有点特殊。这是什么原理?

这里mysql又有个优化:

  1. 如果where有索引,order by也有索引
    默认情况下,先执行where,扫描用到的索引,找出符合条件的行,再按照order by在内存中进行排序。
  2. 但是如果在1的情况下,有limit,并且limit比较小
    则会先执行order by,扫描用到的索引,再回表判断where是否符合条件。取够limit条符合条件的行就返回了,并不会扫描完所有索引。

四、总结

对比三、四小节,可以看出:加索引之后,部分情况下,扫描的行数还变多了,并且使用了内存排序。
所以,加索引不是万能的,不要想当然,要根据实际业务进行分析和测试。

参考

《sql查询调优之where条件排序字段以及limit使用索引的奥秘》
《sql order by与索引之间的关系(where条件出现字段才有效)》

你可能感兴趣的:(数据库,mysql,索引,排序,limit,分页)