出现场景
在生产环境中一些数据量比较大的情况下,我们可能会遇到。
但是这个数据量也没有大到需要使用大数据的工具的地步,都是存在Mysql里面的。可能会有一些明细相关的查询。比如红包的领取情况之类的。那么可能会遇到深分页的问题。
深分页的定义
大家都写过分页查询,通过mysql的limit关键字,例如我要查第一页10条,那么就是limit 0,10。
这看起来没啥问题。
例如数据量很大,页数很多,我查第100000页的10条,那就是limit 100000,10。
你就会发现执行速度明显变慢,这就是深分页问题造成的。同样的查询数据量,深分页可能1s左右,但是你查最初的分页的时候,可能只需要几毫秒。
举例说明
select id, name from red_packet where create_time > '2022-06-13 00:00' limit 0,10;
select id, name from red_packet_detail where create_time > '2022-06-13 00:00' limit 100000, 10;
查询过程
-
假设我们的create_time是一个二级索引,我们先要找到所有满足记录的条件,拿到非聚集索引上面记录的主键id。
-
到聚集索引进行回表,查询数据。
-
扫描我们要查询的limit数据,从0开始不断扫描。最后抛弃前100000条。
原因
- limit要扫描1000010条数据,并且进行丢弃。
- 扫描更多数据也意味着回表的数据更多。
解决方案
子查询优化
select id, name FROM red_packet_detail where id >= (select a.id from red_packet_detail a where a.create_time >= '2022-06-13 00:00' limit 100000, 1) LIMIT 10;
偏移法(要知道上次查询的id,并且id自增)
select id, name FROM red_packet_detail where id > 10000 order by id limit 10;