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

使用Mongoose向MongoDB插入百万级CSV数据时JS堆内存溢出如何解决

问题根因

你前两次的实现均将全量300万条过滤后的记录全部缓存到了内存中的results数组,Node.js默认堆内存上限仅为1~4GB(随版本、系统架构变化),完全无法承载如此大的数据集,因此不管后续是否做分批插入,都会触发堆内存溢出。

最优实现方案

核心思路是基于流的背压控制,边读取CSV边批量插入数据库,内存中仅保留当前待插入的批次数据,不缓存全量数据,完全规避全量数据加载到内存的问题。

实现代码

const fs = require('fs');
const csv = require('csv-parser');
const mongoose = require('mongoose');
// 替换为你实际定义的PhotoModel路径
const PhotoModel = require('./models/photo');

async function importCsvToMongo() {
  // 批次大小可根据服务器配置调整,建议范围500~2000
  const BATCH_SIZE = 1000;
  let currentBatch = [];
  let stream;

  return new Promise((resolve, reject) => {
    stream = fs.createReadStream('myFile.csv')
      .pipe(csv())
      .on('data', async (data) => {
        // 过滤id为48的记录
        if (data.id !== '48') {
          currentBatch.push(data);
        }
        // 攒够批次大小后暂停读流,插入完成后再恢复
        if (currentBatch.length >= BATCH_SIZE) {
          stream.pause();
          try {
            // ordered: false表示单条插入失败不阻断同批次其他记录插入
            await PhotoModel.insertMany(currentBatch, { ordered: false });
            currentBatch = [];
            stream.resume();
          } catch (err) {
            reject(err);
          }
        }
      })
      .on('end', async () => {
        // 插入最后不足一批的剩余数据
        if (currentBatch.length > 0) {
          try {
            await PhotoModel.insertMany(currentBatch, { ordered: false });
          } catch (err) {
            reject(err);
            return;
          }
        }
        console.log('全部数据导入成功');
        resolve();
      })
      .on('error', (err) => {
        reject(err);
      });
  });
}

// 启动导入,替换为你的MongoDB连接地址
mongoose.connect('mongodb://localhost:27017/你的数据库名')
  .then(() => importCsvToMongo())
  .then(() => mongoose.disconnect())
  .catch(err => {
    console.error('导入失败:', err);
    mongoose.disconnect();
  });

优化建议

  • 导入前可先删除集合的非必要索引,待导入完成后再重建,可大幅提升导入速度
  • 若存在重复主键等冲突场景,可将insertMany替换为批量updateOne搭配upsert: true参数处理冲突
  • 特殊场景下如果需要进一步提升导入速度,可适当调大BATCH_SIZE,或执行脚本时添加参数node --max-old-space-size=8192 脚本文件名.js临时提升Node.js堆内存上限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 12:36:04