如何高效实现Mongo大规模数据导入及去重合并?
MongoDB 50万条数据合并导入效率优化方案
一、用MongoDB原生工具替代自定义代码(最快方案)
直接借助mongoimport工具完成导入和去重,比自行编写代码效率高几个数量级:
- 导入carsA到cars集合:
若数据为CSV格式,替换mongoimport --db 你的数据库名 --collection cars --file carsA.json --jsonArray --writeConcern "{w:1}"--jsonArray为--type csv --headerline即可。 - 导入carsB并自动去重:
利用--upsert和--upsertFields参数,让MongoDB自动根据car_id判断插入新数据或跳过重复项:mongoimport --db 你的数据库名 --collection cars --file carsB.json --jsonArray --upsert --upsertFields car_id --writeConcern "{w:1}"
二、自定义代码导入的优化技巧(若必须用代码实现)
如果一定要自行编写导入逻辑,调整以下几点可大幅提升效率:
- 增大批量写入的批次大小:不要局限于5000条,根据单条文档大小调整为1万~2万条/批(文档越小,批次可设置越大)。
- 关闭自动索引维护:导入前先删除
cars集合的car_id索引,完成导入后再重建。索引会严重拖慢写入速度,批量导入后统一建索引比边写边建高效得多。 - 使用
bulkWrite的无序写入:设置ordered: false,让MongoDB并行处理批量操作,无需等待前一批执行完成。 - 原子去重,避免先查后插:用
updateOne配合upsert: true,让MongoDB在服务器端完成「检查-插入/跳过」的原子操作,省去客户端查询的网络开销:// Node.js 示例 const { MongoClient } = require('mongodb'); async function importCarsB() { const client = await MongoClient.connect('mongodb://localhost:27017'); const db = client.db('你的数据库名'); const cars = db.collection('cars'); // 假设carsB数据已读入data数组 const operations = []; for (const doc of data) { operations.push({ updateOne: { filter: { car_id: doc.car_id }, update: { $set: doc }, upsert: true } }); // 每1万条执行一次批量操作 if (operations.length === 10000) { await cars.bulkWrite(operations, { ordered: false }); operations.length = 0; } } if (operations.length > 0) { await cars.bulkWrite(operations, { ordered: false }); } await client.close(); } - 调整写入确认级别:若对实时一致性要求不高,设置
writeConcern: { w: 0 },让MongoDB无需返回写入确认,进一步提升速度。
三、MongoDB服务器临时配置优化
导入期间可临时调整以下配置(完成后可改回):
- 增大WiredTiger缓存:修改
mongod.conf中storage.wiredTiger.engineConfig.cacheSizeGB,设置为服务器内存的50%左右。 - 禁用日志预写(谨慎使用,仅适用于可重新导入的数据):设置
storage.journal.enabled: false,避免日志写入带来的额外开销。
内容的提问来源于stack exchange,提问作者rockstardev
相关产品推荐
相关产品推荐

