分页设计问题梳理

本文详细探讨了分页设计的常见形式和两大难点问题——深分页和数据重复/丢失。对于深分页,文章列举了MySQL的多种分页实现方式,包括limit + offset、max_id + limit、max_id + limit + offset、subquery + inner join和subquery,分析了各自的优缺点。数据重复/丢失问题主要出现在数据顺序和总量变化的场景下,如排行榜、文章留言列表和评论列表。针对这些问题,文章提出了一次性取出、排行榜快照和通过变动记录表拿数据等解决方案。最后,文章简要介绍了ES的分页接口实现,包括from + size、search after和scroll api,适应不同场景的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

常见分页形式

在列表页实现分页展示逻辑是十分常见的需求,但针对不同的场景和产品需求,分页功能有不同的表现形式。常见的有如下几种。

1、滚动翻页

下滑自动下一页,展示直到当前页的所有内容,不显示总页数、总条数,不支持上一页、跳页,不支持page size设置

2、上/下一页

只支持简单的上/下一页的操作,不显示总页数、总条数,不支持跳页,不支持page size设置

3、跳页(最为常见)

支持上/下一页、跳页,page size固定,不显示总页数

4、跳页、显示总页数

支持上/下一页、跳页,page size可设置,显示总页数

分页设计的两大难点问题

传统分页的话,一般只考虑传页数(page)和每页数据条数(limit)这两个参数给后端,为了方便后面描述,我们给这个传参方式起个名字叫传统分页。
传统分页存在两个突出的问题:

  1. 深分页:翻页过深导致拉取数据量过大,耗费大量IO和内存,极端情况可能导致OOM,效率低下
  2. 数据重复/丢失:数据变动导致分页数据重复/丢失

深分页

深分页问题在分页设计中较为常见,大家在设计时一般都会考虑到这个问题。该问题在分库分表或者存在数据分区的场景下更为严重。
面对不同的需求场景,解决深分页问题的方法也有所不同。下面以常见的利用MySQL实现分页的方案做一个简单的分析。

MySQL实现分页

方式1:limit + offset

select * from { {table}} order by id limit m, n;

很简单,该语句的意思就是查询m+n条记录,去掉前m条,返回后n条。
无疑该查询能够实现分页,但m越大,查询性能就越低,因为MySQL需要扫描全部m+n条记录(在存在数据分区的情况下,需要扫描(m+n)*分区数条记录)。
适用场景:支持跳页,但要求数据量较小,深分页带来的存储和性能压力可以接受

方式2:max_id + limit

select * from { {table}} where id > { {max_id}} order by id limit n;

该查询同样会返回后n条记录,却无需像方式1扫描前m条记录,但必须在每次查询时拿到上一次查询(上一页)的最大id。
该查询的问题也在于我们不一定能拿到这个id,比如当前在第3页,需要查询第5页的数据,就不行了。
适用场景:不支持跳页,只能上下翻页

方式3:max_id + limit + offset

为了避免方式2不能实现的跳页查询,就需要结合方式1。
性能需要,m得尽量小,比如当前在第3页,需要查询第5页,每页10条数据,而当前第3页的最大id为max_id,则:

select * from table where id > { {max_id}} order by id limit 10, 10;

该查询方式实际是方式1和方式2的结合,它只能部分地解决方式2的问题。
如果当前在第2页,要查第1000页(跳转尾页),查询的数据量仍然很大(需要查询10*998条数据,然后过滤出后10条)。
适用场景:支持跳页,相对方式1可以适用于较大的数据量,但极端情况(从第一页跳页)下会退化为方式1。

方式4:subquery + inner join

select * from table as a inner join (select id from table order by id limit m, n) as b on a.id = b.id order by a.id;

该查询同方式1一样,m的值可能很大,但由于内部的子查询只扫描了id字段,而非全表,所以性能要强于方式1(可以命中覆盖索引设置主键索引),并且能够解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值