limit

SELECT * FROM users ORDER BY id LIMIT 10, 20;

从偏移量为10开始,返回20行记录,即第11到第30行记录

如果是limit 20000000 10,那会把前两千万条数据查出来,然后丢弃,然后从第20000001行开始返回10行,性能极低,这就是深度分页问题

深度分页优化:

可以把每次查询到的最大id记录下来,下次从这个id开始继续查:

SELECT * FROM users WHERE id > last_max_id ORDER BY id LIMIT 10;

但这种方案不能往回查,只能一页一页往后查,且查询过程中不能有新增

id不能重复,不然就会陷入死循环,比如一页的10条,ID全是12,last_max_id也为12,那么下一页的查询还是>= 12

覆盖索引 + 子查询:

SELECT * FROM users WHERE id > (SELECT id FROM users ORDER BY id LIMIT 20000000, 1) ORDER BY id LIMIT 10;

子查询在主键索引上查询,不需要回表,得到第20000001的id,然后主查询根据id进行范围查询

使用ES,ES也有深分页问题,但影响比MySQL小点

【【IT老齐074】从76237到753毫秒,海量数据大页码MySQL查询该如何优化?】https://www.bilibili.com/video/BV1PL411g7Vj?vd_source=cae07b1dce3e6abe67fcf72c43031ede

产品上解决问题: