刷数的最佳姿势
最佳实践
游标
伪代码
max_id = 0while True: # 使用max_id作为起始ID查询数据 data = query_data(start_id=max_id, limit=page_size)
if not data: break # 没有数据,结束查询
process_data(data)
# 更新max_id为当前批次的最大ID max_id = get_max_id(data)
刷数代码抽象 落地的Java代码
优缺点
使用最大ID作为分页起始ID(通常称为”ID游标分页”)相比传统的 LIMIT 和 OFFSET 分页方法,有以下几个显著优势:
-
性能优势
- 传统 LIMIT/OFFSET:随着页码增加,OFFSET 需要跳过大量记录,查询性能急剧下降
- ID游标分页:每次只查询大于上一批最大ID的数据,查询速度始终保持稳定
-
数据一致性
- LIMIT/OFFSET:在分页过程中,如果有新数据插入,可能导致同一条记录重复出现或被遗漏
- ID游标分页:使用严格的ID范围,可以避免数据重复和遗漏问题
-
扩展性
- 适合大数据量场景,特别是分布式数据库和海量数据查询
- 在数据量超过百万、千万级别时,性能优势更加明显
示例对比:
传统 LIMIT/OFFSET 方式:
-- 查询第 N 页,每页 10 条SELECT * FROM tableLIMIT 10 OFFSET (N-1) * 10
ID游标分页方式:
-- 查询大于上一批最大ID的 10 条数据SELECT * FROM tableWHERE id > last_max_idLIMIT 10
实际应用中,ID游标分页特别适合:
- 实时数据流处理
- 消息系统
- 日志查询
- 高并发场景下的数据获取
缺点是不直观,需要额外的业务逻辑来维护和传递”最后一个ID”。
自己的实践
- 从mysql刷数据到es
- 从mongodb读取历史数据,刷mysql — 使用游标很稳定,任务跑了6个多小时,没有性能问题。如果使用分页,十几分钟就会出现严重的性能问题。
所以在操作大批量的数据的时候,需要优先考虑游标形式。为了保持游标的连续性,建议在内存中做条件处理,否则可能导致下一次取出的数据为空,中断整个流程。
网站当前构建日期: 2025.02.28