主要观点总结
本文主要讨论了sharding-jdbc分页查询机制在深分页时导致的内存过大问题,分析了问题的根本原因,并提出了几种解决方案,包括使用连续分页、利用数据库特性(ROW_NUMBER()函数)、Sharding-Jdbc的limit优化配置和业务设计规避深分页等方法。
关键观点总结
关键观点1: sharding-jdbc分页查询机制介绍
Sharding-Jdbc解析原始SQL,根据分片键和分片算法改写SQL并路由到所有相关分片执行。收集所有分片的结果集进行全局排序,然后返回满足记录的条数。
关键观点2: 深分页导致内存过大的原因
每个分片都需要返回offset+row_count条数据,导致内存中需要处理的数据量急剧增加。全局排序和截取过程也需要大量内存和CPU。
关键观点3: 解决方案
通过避免每个分片返回大量不需要的数据,减少内存中需要归并的数据总量。具体方法包括使用连续分页、利用数据库特性(ROW_NUMBER()函数)、Sharding-Jdbc的limit优化配置和业务设计规避深分页等。
正文
假设我们要执行的业务SQL,如下:
SELECT * FROM orders ORDER BY create_time DESC LIMIT 10000, 10
基本原理
-
Sharding-Jdbc 首先解析你的原始 SQL,识别出 LIMIT offset, row_count
-
根据配置的分片键(如 order_id 或 user_id)和分片算法,将这条 SQL 改写并路由到所有相关的物理分片(表)上执行。
-
Sharding-Jdbc客户端会收集所有分片返回的结果集,进行全局排序,然后去满足记录的row_count 条记录
回到我们的原始SQL:SQL:
SELECT * FROM orders ... LIMIT 10000, 10
Sharding-Jdbc 会改写SQL为:
SELECT * FROM orders_0 ... LIMIT 0, 10010
SELECT * FROM orders_1 ... LIMIT 0, 10010
然后发到每个分片执行。
为什么要这么每个分片都执行呢?
为了确保从每个分片获取到足够的数据,以便在内存中进行全局排序和精确截取最终的第 10000 到 10009 条记录(总共 10 条)。因为数据分散在各个分片,Sharding-Jdbc 无法预知哪个分片的数据最终会排在全局结果的哪个位置。
2. 深分页导致内存过大的原因