limit 10 和 limit 60000,10
- 实际上 limit 10 = limit 0,10
- 两者的区别在于开始的 offset 不一样,一个是0,一个是10
limit 的执行过程
针对如下sql
select*from user order by id limit 10
1、执行器 调用 存储引擎层查询到 0 - 10 条数据
2、server层拿到 0 - 10 数据返回
select*from user order by id limit 6000000,10
1、执行器 调用 存储引擎层查询到 0 - (6000000 + 10) 条数据 2、server层拿到 0 - (6000000 + 10) 数据(这里涉及到数据的copy),根据offet抛弃掉前6000000条 再返回
基于主键索引和普通索引的limit
-
注意前提:(一般情况下 select 的字段,在索引中不能全部覆盖)
-
基于主键索引和普通索引的limit 的区别在于 server层拿到存储引擎返回的数据,
如果是普通索引limit的话,会先将所有数据逐条回表拿到所有数据,然后再抛弃offset之前的数据(参考sql的执行顺序),如果是主键索引则不需要回表,其余操作与普通索引limit一致
优化方向
- 存储引擎层多余数据返回给server层的copy耗时
-
-
查询的过程中记录每次的最大的id,在sql中增加 where id > lastMaxId
-
- 如果是普通索引的情况下多次回表耗时
-
-
可能话,索引覆盖到查询字段 比如 联合索引 (name,age)= (name,age,id),如果where 条件中有非等值条件的情况下比如 select name,age from user where name=a and age=20 and create_time > xxx and id > xx order by id limit start,size,可以考虑建立 如 (name,age,id)只关注等值条件的联合索引。此时如果 创建 (name,age,id,create_time)create_time实际上也用不上,因为只有等值条件后 order by 是有序,如果加上create_time就无序了。
-