分页设计问题梳理

常见分页形式

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

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(可以命中覆盖索引设置主键索引),并且能够解决方式2和方式3不能解决的问题。
适用场景:支持跳页,相对方式1和方式3可以适用于更大的数据量

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java用户图形界面分页设计,可以通过使用JTabbedPane组件和JPanel来实现。以下是大致的步骤: 1. 创建一个JFrame窗口,设置其布局为BorderLayout。 2. 创建一个JTabbedPane组件,添加到窗口的中央区域。 3. 创建多个JPanel组件,每个JPanel组件对应一个分页,将它们添加到JTabbedPane组件中。 4. 在每个JPanel组件中添加需要展示的组件,如标签、按钮、输入框等。 5. 根据需要,可以在每个JPanel组件中添加滚动条来实现长内容的分页展示。 6. 可以在JPanel组件中添加事件监听器,实现用户交互功能。 下面是一个简单的示例代码: ``` import javax.swing.*; import java.awt.*; public class UserGUI extends JFrame { public UserGUI() { // 创建窗口 setTitle("用户管理系统"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(500, 400); setLayout(new BorderLayout()); // 创建分页 JTabbedPane tabbedPane = new JTabbedPane(); JPanel panel1 = new JPanel(); JPanel panel2 = new JPanel(); JPanel panel3 = new JPanel(); tabbedPane.addTab("用户信息", panel1); tabbedPane.addTab("用户添加", panel2); tabbedPane.addTab("用户删除", panel3); // 在分页中添加组件 panel1.add(new JLabel("用户信息展示")); panel2.add(new JLabel("用户添加表单")); panel3.add(new JLabel("用户删除表单")); // 将分页添加到窗口中央 add(tabbedPane, BorderLayout.CENTER); setVisible(true); } public static void main(String[] args) { new UserGUI(); } } ``` 这段代码创建了一个名为“用户管理系统”的窗口,包含三个分页:“用户信息”、“用户添加”和“用户删除”。在每个分页中,分别添加了一个标签。这只是一个简单的示例,你可以根据需要添加更多组件和交互功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值