如何高效地遍历 MongoDB 超大集合?

本文探讨了在Node.js中使用mongoose连接MongoDB时,如何避免遍历超大集合导致内存不足的问题。错误方法是使用find()一次性获取所有document,而正确的做法是利用find().cursor().eachAsync(),按需逐个处理document,以减少内存消耗。通过mgodatagen生成大量测试数据,并提供测试代码以验证效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文使用的编程语言是 Node.js,连接 MongoDB 的模块用的是mongoose。但是,本文介绍的方法适用于其他编程语言及其对应的 MongoDB 模块。

错误方法:find()

也许,在遍历 MongoDB 集合时,我们会这样写:

const Promise = require("bluebird");

function findAllMembers() {
   
   
    return Member.find();
}

async function test() {
   
   
    const members = await findAllMembers();
    let N = 0;
    await Promise.mapSeries(members, member => {
   
   
        N++;
        console.log(`name of the ${
     
     N}th member: ${
     
     member.name}`);
    });
    console.log(`loop all ${
     
     N} members success`);
}

test();

注意,我们使用的是 Bluebird 的mapSeries而非map,members 数组中的元素是一个一个处理的。这样就够了吗?

当 Member 集合中的 document 不多时,比如只有 1000 个时,那确实没有问题。但是当 Member 集合中有 1000 万个 document 时,会发生什么呢?如下:

<--- Last few GCs --->
rt of marking 1770 ms) (average mu = 0.168, current mu = 0.025) finalize [5887:0x43127d0]    33672 ms: Mark-sweep 1398.3 (1425.2) -> 1398.0 (1425.7) MB, 1772.0 / 0.0 ms  (+ 0.1 ms in 12 steps since start of marking, biggest step 0.0 ms, walltime since start of marking 1775 ms) (average mu = 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值