JJava 知识库
JAVA INTERVIEW

高频面试题

MySQL进阶约 2 分钟

运营要导出几百万条订单,LIMIT 越翻越慢,你会怎么改造查询和导出流程?

参考回答约 2 分钟 · 口语表达
我的判断

几百万订单导出不应由一个同步 HTTP 请求用 OFFSET 翻完,而应改成游标扫描的异步任务,分批写对象存储。

LIMIT 1000000, 1000 需要扫描并丢弃前面一百万行,越往后越慢。我会选择稳定排序键,用上一批最后的时间和 ID 继续:

WHERE tenant_id = ?
  AND (created_at < ?
       OR (created_at = ? AND id < ?))
ORDER BY created_at DESC, id DESC
LIMIT 2000;

导出请求只创建任务并返回 taskId。后台 worker 控制并发,批量读取后流式写 CSV/Parquet 到对象存储,记录游标和进度,失败从检查点恢复;完成后发通知并提供有时效的下载地址。

一致性要和产品确认。要求导出某一时刻快照时,可以先记录截止时间或版本边界,避免任务运行两小时期间新订单不断混入;不建议持有一个两小时数据库事务。

整个链路要限制单租户并发、批大小和下载权限,并监控扫描速率、复制延迟、任务积压和失败重试。

容易答偏踩坑误区
  • 把 OFFSET 改大批次。 页越深仍然越慢。
  • 一次查完放进内存。 应边读边写并有背压。
  • 长事务保持快照。 会阻碍 Undo 清理并放大主库压力。