You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

优化读写:百万级数据分批读写实现(无法使用Spring Batch)

增量式检索并写入百万级数据的实现方案

核心思路:分页分批次查询+逐批写入

直接调用findAll()会把100万+数据一次性加载到内存,极易触发内存溢出。改用分页分批次查询,每次固定拉取一批数据(比如1万或10万条),处理完一批就写入文件并释放内存,循环直到所有数据处理完成,从根本上降低内存压力。

具体代码实现

假设你用的是Spring Data JPA(从dataRepository的用法推断),以下是可直接落地的代码:

int batchSize = 10000; // 每次拉取1万条,可根据单条数据大小、内存情况调整
int pageNum = 0;
boolean hasMoreData = true;

// 用try-with-resources自动关流,避免资源泄漏
try (BufferedWriter bw = new BufferedWriter(new FileWriter(path))) {
    while (hasMoreData) {
        // 分页查询当前批次数据
        Page<Data> dataPage = dataRepository.findAll(PageRequest.of(pageNum, batchSize));
        List<Data> dataList = dataPage.getContent();

        // 逐行写入当前批次
        for (Data data : dataList) {
            bw.write(data.toString());
            bw.newLine(); // 可选,让每条数据单独占一行,方便后续读取
        }
        // 每批写完立即刷盘,避免数据积压在内存缓冲区
        bw.flush();

        // 判断是否还有下一页
        hasMoreData = dataPage.hasNext();
        pageNum++;
    }
} catch (IOException e) {
    // 按需处理异常,比如打日志或抛业务异常
    e.printStackTrace();
}

关键注意事项

  • 调整batchSize:单条数据体积大就调小批次,反之可适当增大,平衡IO频率和内存占用。
  • 流的安全关闭:必须用try-with-resources语法,确保程序异常时文件流也能被正确关闭,避免资源泄漏。
  • 大偏移量性能优化:如果用OFFSET分页,当页码很大时(比如第100页),数据库查询性能会下降。这时可以改用主键范围查询(假设Data有自增主键id),性能更稳定:
    long lastId = 0;
    int batchSize = 10000;
    boolean hasMoreData = true;
    
    try (BufferedWriter bw = new BufferedWriter(new FileWriter(path))) {
        while (hasMoreData) {
            // 按主键范围拉取下一批数据
            List<Data> dataList = dataRepository.findByIdGreaterThan(lastId, PageRequest.of(0, batchSize));
            if (dataList.isEmpty()) {
                hasMoreData = false;
                continue;
            }
    
            // 写入当前批次
            for (Data data : dataList) {
                bw.write(data.toString());
                bw.newLine();
            }
            bw.flush();
    
            // 更新最后一条数据的ID,作为下一批查询的起始条件
            lastId = dataList.get(dataList.size() - 1).getId();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    对应的Repository需要新增查询方法:
    @Repository
    public interface DataRepository extends JpaRepository<Data, Long> {
        List<Data> findByIdGreaterThan(long lastId, Pageable pageable);
    }
    

内容的提问来源于stack exchange,提问作者fragilepriCe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 00:28:20