接上篇:https://developer.aliyun.com/article/1228223?spm=a2c6h.13148508.setting.14.62774f0e61109O
五、 数据查询不分页
在数据查询时,由于未能对未来数据量做出正确的预估,很多情况下都没有考虑数据的分页查询。
1. 普通查询案例
以下是查询过期订单的代码:
当过期订单数量很少时,以上代码不会有任何问题。但是,当过期订单数量达到几十万上千万时,以上代码就会出现以下问题:
• 数据量太大,导致服务端的内存溢出;
• 数据量太大,导致查询接口超时、返回数据超时等;
• 数据量太大,导致客户端的内存溢出。
所以,在数据查询时,特别是不能预估数据量的大小时,需要考虑数据的分页查询。
这里,主要介绍“设置最大数量”和“采用分页查询”两种方式。
2. 设置最大数量
“设置最大数量”是一种最简单的分页查询,相当于只返回第一页数据。例子代码如下:
适用于没有分页需求、但又担心数据过多导致内存溢出、数据量过大的查询。
3. 采用分页查询
“采用分页查询”是指定startIndex(开始序号)和pageSize(页面大小)进行数据查询,或者指定pageIndex(分页序号)和pageSize(页面大小)进行数据查询。
例子代码如下:
适用于真正的分页查询,查询参数startIndex(开始序号)和pageSize(页面大小)可由调用方指定。
4. 分页查询隐藏问题
假设,我们需要在一个定时作业(每5分钟执行一次)中,针对已经超时的订单(status=5,创建时间超时30天)进行超时关闭(status=10)。
实现代码如下:
粗看这段代码是没有问题的,尝试循环100次,每次取1000条过期订单,进行订单超时关闭操作,直到没有订单或达到100次为止。但是,如果结合订单状态一起看,就会发现从第二次查询开始,每次会忽略掉前startIndex(开始序号)条应该处理的过期订单。这就是分页查询存在的隐藏问题:
• 当满足查询条件的数据,在操作中不再满足查询条件时,会导致后续分页查询中前startIndex(开始序号)条满足条件的数据被跳过。
可以采用“设置最大数量”的方式解决,代码如下:
后记
本文是《那些年,我们见过的Java服务端“乱象”》的姐妹篇,前文主要介绍的是Java服务端规范上的问题,而本文主要介绍的是Java服务端方案上的问题。