当前位置: 首页 > news >正文

浅析分批分页查询场景及方案

背景

在日常开发中,不可避免的要用到分批查询或分页查询,其中的场景有很多,有的是WEB页面的分页查询效果,或移动端向下滑动的分页查询,有的则是因为目标数据量巨大,不得已而分批查询。无论是出于性能考虑,还是大报文考虑,抑或页面的效果,分批或分页查询都是研发的日常。

 


 

 

 


 

 

本文尝试,对日常项目用到的分批分页查询做一下方案的回顾和浅析。

查询场景及方案

一、普通分批分页查询场景

方案1 普通LIMIT OFFSET分页查询方式

通过数据库直接LIMIT OFFSET 的方式是最简单,也是最常用的分页查询方式。

SELECTid,warehouse_no,location_no,sku,sku_level,lot_no,pack_code,owner_no,extend_content
FROMst_stock
WHEREdeleted = 0AND warehouse_no = '6_666'
ORDER BYid ASC 
LIMIT 100,10

该方法直接简单,开发和运维简单,可读性高,但当offset值(偏移量)非常大时,弊端也比较明显:深分页性能问题比较严重,例如 LIMIT 1000000, 10 。

 

当执行LIMIT 1000000, 10时,SQL的处理流程是:

扫描并读取前1,000,000条记录

丢弃这1,000,000条记录

返回接下来的10条记录

这意味着即使只需要10条数据,数据库也必须访问和处理大量的"无用"数据。

 

简言之,深分页,IO开销大:需要读取大量无用数据页;内存消耗高:大量数据加载到内存后被丢弃;CPU消耗高:排序、过滤操作消耗大量CPU资源。

 

方案2 基于子查询或二次查询的分页查询

SELECTs.id,warehouse_no,location_no,sku,sku_level,lot_no,pack_code,owner_no,extend_content
FROMst_stock s
JOIN(SELECTidFROMst_stockWHEREdeleted = 0AND warehouse_no = '6_666'ORDER BYid ASC LIMIT 100,10)s2
ONs.id = s2.id

SELECTs.id,s.warehouse_no,s.location_no,s.sku,s.sku_level,s.lot_no,s.pack_code,s.owner_no,s.extend_content
FROM st_stock s
WHERE EXISTS (SELECT 1FROM (SELECT idFROM st_stockWHERE deleted = 0AND warehouse_no = '6_666'ORDER BY id ASCLIMIT 100,10) AS s2WHERE s.id = s2.id
);

 

除了直接在SQL中进行分页处理,还可以通过二次查询的方式来实现。

第一步,先分页查询id列表;

SELECT id
FROM st_stock
WHERE deleted = 0AND warehouse_no = '6_666'
ORDER BY id ASC
LIMIT 100,10;

id字段有主键索引,避免回表。

 

第二步,以第一步的id列表作为in条件,查询库存信息。

SELECTid,warehouse_no,location_no,sku,sku_level,lot_no,pack_code,owner_no,extend_content
FROM st_stock
WHERE id IN (id1, id2, id3, ...);

 

注意:下面的SQL方式是错误的,SQL语法不支持:

SELECTid,warehouse_no,location_no,sku,sku_level,lot_no,pack_code,owner_no,extend_content
FROMst_stock swhere id in (SELECTidFROMst_stockWHEREdeleted = 0AND warehouse_no = '6_666'ORDER BYid ASC LIMIT 100,10)

SQL 错误 [1235] [42000]: This version of SQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

解决方案就是使用上面的方式实现。

 

方案3 游标分页,滚动式查询

SELECTid,warehouse_no,location_no,sku,sku_level,lot_no,pack_code,owner_no,extend_content
FROMst_stock
WHEREdeleted = 0AND warehouse_no = '6_666'AND id > 100
ORDER BYid ASC 
LIMIT 10

与方案一相比,最大的区别是增加了id条件,本次id的条件是上一次查询结果集中的最大id,通过id滚动式查询,缩小检索范围。

 

 


 

上图就是一个游标分页查询的案例。

 

二、动态数据分批分页导出查询场景

对于动态变化的数据,想要分批分页导出,而且想要保证数据的准确性,该如何处理呢?

方案1 对目标数据加锁

将导出条件对应的目标数据锁定,导出结束后再解锁这批数据。导出时间被锁定的数据行,不能update、delete,可以select。

 SKU……locked
2019609892142206976 123 …… 1
2019695225349345280 456 …… 1
2019326832070885376 789 …… 1
2027414057350348800 110 …… 0
2027414069316685824 118 …… 0

 

优势

可以保持在导出期间稳定导出数据,减少因为数据的动态变化影响数据的准确性。
如果在导出期间,符合条件的数据库行有新增(insert),在数据库主键ID递增的情况下,新增行的id更大,排序在后,可以正常导出这部分新增数据,不受影响。

 

劣势

锁定的这部分导出数据,在导出期间,只读,不能执行写服务,相当于停产导出,适合于生产低谷时段或停产时段进行导出。

 

 

方案2 生成导出数据快照

将导出条件对应的目标数据生成导出库存快照数据,导出执行是将本次版本的快照数据导出,导出数据快照过时可以清理。

实时数据

idSKU……
2019609892142206976 123 ……
2019695225349345280 456 ……
2019326832070885376 789 ……
2027414057350348800 110 ……
2027414069316685824 118 ……

 

快照数据

idSKU……
2019609892142206976 123 ……
2019695225349345280 456 ……
2019326832070885376 789 ……

 

优势

在数据导出期间稳定导出数据,每次导出的数据都有单独的导出数据快照版本,导出期间数据的准确性得到保障。
在数据导出期间,即使有数据的变化,也不影响导出效果。不锁数据行,不影响生成生产作业。

 

劣势

如果在导出期间,符合条件的数据库行有新增(insert),这部分数据即使符合导出条件,也不会导出,因为这部分新增的数据在导出数据快照之后生成,并未在快照数据中。
需要生成导出数据快照,导出数据快照版本需要单独的库表存储,同时也会占用磁盘资源。
导出数据快照生成期间,倘若符合条件的数据行有变化,需要对快照数据生成特殊处理,比如一次性生成快照等方式。

 

三、内存分页查询场景

在日常研发过程中遇到的分页查询,大部分都可以借助SQL数据库、ES等存储中间件自身的分页功能实现,但个别场景下并不符合,比如数据并未存储在SQL数据库或ES中,而是内存计算出来的一种结果数据;或者数据库中存储的数据维度并不符合,并不能通过简单的GROUP BY等方式实现维度加工;或者数据库中存储的数据,需要通过第三方RPC远程接口实时获取特殊属性打标过滤后,才可以作为目标数据使用。

在这些场景下,我们会用到内存分页的方式处理。

 

内存分页方案

 


 

 

 


 

 

上面的示例,是一个简单的内存分页处理方式。

总结

本文回顾了日常研发过程中,经常遇到的普通分批分页查询场景、动态数据分批分页导出查询场景、内存分页查询等场景,探讨了对应的解决方案。方案并非固定一成不变的,也有各自的利弊和局限性,在合适场景下,选择合适的方案即可。

http://www.jsqmd.com/news/582118/

相关文章:

  • 探秘食品级真空上料机生产厂家,解锁食品输送新体验 - 品牌推荐大师
  • Sketch设计文件命名规范化的技术解决方案:RenameIt批量重命名插件深度解析
  • swagger转word--python版本
  • 5分钟完全指南:用开源tcc-g15掌控Dell G15散热,告别官方AWCC卡顿
  • d2s-editor:革新性暗黑2存档管理的一站式工具
  • 遇到一个口头机遇的答辩准备2(ai告诉的要点)
  • 2026最新西南考银行培训推荐!贵州/贵阳优质银行招考培训权威榜单 - 十大品牌榜
  • 突破Windows远程桌面限制:RDP Wrapper Library全方位应用指南
  • P1884 [USACO12FEB] Overplanting S
  • 如何避免机械拼凑式的基金申请书撰写
  • idea比对两个文件差异
  • 随笔其二
  • 基于蓝牙及GSM的智能防盗系统设计与实现
  • 2026全自动三坐标测量机品牌实力榜单:谁更值得选? - 品牌推荐大师
  • 华硕笔记本终极性能控制指南:用GHelper取代臃肿的Armoury Crate
  • 3步掌握创意工坊壁纸高效获取工具
  • 2026届毕业生推荐的十大AI写作助手推荐榜单
  • 3个核心价值:Tiktokenizer如何解决AI开发中的令牌管理难题
  • 佰力博压电 d33-F(动态力)测试:精准表征压电材料动态性能
  • 2026最新西南银行备考/银行招聘培训推荐!贵阳地区优质机构权威榜单 - 十大品牌榜
  • AgentCPM-Report轻量化部署方案:Pixel Epic镜像免环境配置快速上手指南
  • 2026最新舞蹈艺考培训学校推荐!云南昆明优质机构权威榜单发布 - 十大品牌榜
  • 面向对象进阶 继承
  • Windows系统下Docker Desktop环境的完整迁移方案,包含镜像、容器和数据卷的备份恢复方法 将笔记本上Docker Desktop 东西迁移本地PC 电脑Docker Desktop上
  • 第三方系统集成若依权限校验
  • 【Python实战】搭建AI数字人对话系统:从语音识别到虚拟形象的全流程实现
  • 【数据要素+数据资产合集】100余份数据要素+数据资产方案资料合集(PPT+WORD)
  • MJh代码混淆实战指南:使用Obfuscar构建坚不可摧的安全防线
  • 基于Matlab的轴承-空心转轴-飞轮不同耦合类型动力学分析
  • N_m3u8DL-RE:跨平台流媒体解决方案的全方位技术指南