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

Spring Boot+MySQL环境下ZStandard压缩大体积JSON批量导入性能优化及速度合理性咨询

你的导入速度完全不合理,而且当前代码存在多个致命瓶颈,咱们一步步来拆解和优化:

首先,先戳破核心问题:你提到文件是ZStandard(zstd)压缩的,但当前代码直接用FileReader读取——这根本不对!zstd是二进制压缩格式,FileReader读出来的是乱码,你现在的解析逻辑能跑通都奇怪(要么你实际代码里有解压步骤没贴,要么数据其实没被正确解析),这是第一个要修复的点。

接下来,咱们逐个分析瓶颈和优化方案:

1. 先解决最基础的解压问题

你需要用zstd的Java库来解压数据流,推荐用com.github.luben:zstd-jni(Maven依赖)。替换掉你的FileReader,用ZstdInputStream包裹文件输入流,再转成BufferedReader:

// 添加Maven依赖
// <dependency>
//     <groupId>com.github.luben</groupId>
//     <artifactId>zstd-jni</artifactId>
//     <version>1.5.5-12</version>
// </dependency>

// 读取压缩文件的正确方式
try (ZstdInputStream zstdIn = new ZstdInputStream(new FileInputStream("/opt/tomcat/" + fileName));
     BufferedReader br = new BufferedReader(new InputStreamReader(zstdIn))) {
    // 后续处理逻辑
}

2. 消除代码里的低效操作

你的当前代码有两个超级浪费的点:

  • 重复反序列化JSON:每次循环调用两次om.readValue(line, Data.class),完全可以解析一次存起来复用。
  • 单条数据库操作+同步查询:每次循环都查一次existsByAddress,再单条save,数据库IO是最大的瓶颈。

优化步骤:

a. 批量加载现有address到内存,避免重复查询

先把数据库里所有已存在的address拉到一个HashSet里,这样判断是否存在直接在内存查,速度快几个数量级:

// 提前加载所有已存在的address(如果数据量过大,可分批加载,但30GB的JSON对应的address数量如果不是亿级,内存应该能扛)
Set<String> existingAddresses = new HashSet<>(rootRepository.findAllAddresses());
// 这里需要你在Repository里加一个自定义方法:List<String> findAllAddresses();

b. 批量收集待插入数据,批量写入数据库

不要单条save,而是收集到一个列表,达到阈值(比如1000条)就批量插入:

ObjectMapper om = new ObjectMapper();
List<Data> batchData = new ArrayList<>(1000);
String line;
while ((line = br.readLine()) != null) {
    Data data = om.readValue(line, Data.class);
    if (!existingAddresses.contains(data.getAddress())) {
        batchData.add(data);
        // 达到批量阈值就写入
        if (batchData.size() >= 1000) {
            rootRepository.saveAll(batchData);
            batchData.clear();
        }
    }
}
// 处理剩余的最后一批数据
if (!batchData.isEmpty()) {
    rootRepository.saveAll(batchData);
}

3. 进阶优化:利用多线程提升处理速度

单线程处理30GB数据肯定慢,用生产者-消费者模式,让解压、解析、写入分开在不同线程执行:

  • 生产者线程:负责解压读取行数据,放到阻塞队列里。
  • 多个消费者线程:从队列里取行,解析成Data对象,判断是否存在,收集批量数据后写入数据库。

注意:要配置足够的数据库连接池大小(比如Tomcat的dbcp2配置maxTotal到20-30),避免连接不够用。

4. 数据库层面的关键优化

  • 给address加唯一索引:这不仅能让findAllAddresses更快,还可以直接用INSERT ... ON DUPLICATE KEY UPDATE或者INSERT IGNORE,彻底省去先查询再插入的步骤——让数据库帮你去重,效率更高。
  • 关闭自动提交:在批量插入时,手动控制事务,比如每插入N条提交一次,减少事务开销。
  • 调整MySQL参数:比如增大innodb_buffer_pool_size(建议设为服务器内存的50%-70%)、innodb_log_file_size、max_allowed_packet等,优化写入性能。

预期效果

优化后,你的导入速度至少能提升20-50倍——按30GB计算,应该能在几小时内完成,而不是原来的240小时。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 04:07:52