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

使用activerecord-import批量导入CSV并更新重复值时出现内存不足报错

问题解决方案

你遇到的PG内存溢出错误核心原因是单次导入全量180万条记录,单条SQL的体积超出了PG的内存分配上限,和你调整的重复更新字段配置无关,按以下优先级优化即可解决:

1. 优先做分批导入

不要把所有CSV行一次性存入数组后全量导入,每攒1000~5000行就调用一次import,同时避免全量数据常驻应用内存:

BATCH_SIZE = 3000
converter = lambda { |header| header.downcase }
Zip::File.open(content) do |zip|
  zip.each do |entry|
    next unless final === entry.name
    data = zip.read(entry)
    batch = []
    CSV.parse(data, headers: true, header_converters: converter, encoding: 'ISO-8859-1') do |row|
      batch << row.to_h
      if batch.size >= BATCH_SIZE
        Carrier.import(
          batch,
          on_duplicate_key_update: {conflict_target: [:dot_number], columns: [:mcs150_date]},
          validate: false # 确认CSV数据合规的情况下一定要加,大幅提升性能
        )
        batch.clear
      end
    end
    # 处理最后一批不足BATCH_SIZE的记录
    Carrier.import(
      batch,
      on_duplicate_key_update: {conflict_target: [:dot_number], columns: [:mcs150_date]},
      validate: false
    ) if batch.any?
  end
end

2. 提前过滤完全重复的记录

你提到大部分记录是完全重复无需处理的,先预查已有数据筛掉无效记录,能把实际导入量从180万压缩到几万级别:

  • 先从CSV里提取所有dot_number和对应的mcs150_date,存在临时哈希里
  • 批量查询Carrier表中已存在的这些dot_number的mcs150_date,和临时哈希对比
  • 只保留日期不一致的待更新记录、和不存在的待新增记录,再走分批导入

3. 可选优化项

  • 导入前临时删除Carrier表的非唯一索引,导入完成后再重建,能减少导入时的索引维护开销
  • 若CSV数据来源可靠,可添加recursive: false、timestamps: false(如果不需要自动更新更新时间的话)参数,进一步降低activerecord-import的额外开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:39:04