V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Dnlyao
V2EX  ›  Node.js

请问一下,查询万条数据,内存不断增长的解决方法。

  •  
  •   Dnlyao · 2022-04-08 10:22:59 +08:00 · 7260 次点击
    这是一个创建于 720 天前的主题,其中的信息可能已经有所发展或是发生改变。

    node+mongoose ,利用 pm2 管理项目,内存限制 512MB 。业务是查询记录,然后导出 excel 。目前是手动将万条数据 id ,1000 条一组跑循环查询,放入数组,最后拿数组生成文件。但每次都内存超出,项目重启了。

    14 条回复    2022-04-11 10:14:53 +08:00
    Dnlyao
        1
    Dnlyao  
    OP
       2022-04-08 10:25:44 +08:00
    let ids = []
    let total = await TradeRecord.find(conditions).select('id').sort({'tradeAt': -1})
    for (let item of total) {
    ids.push(item._id)
    }
    for (let index = 1; index <= Math.floor(ids.length / 10) + 1; index++) {
    let tradids = []
    let i = index - 1 > 0 ? (index - 1) * 10 : 0
    if ((index * 10) < ids.length) {
    tradids = ids.slice(i, index * 10)
    } else {
    tradids = ids.slice(i)
    }
    if (tradids.length > 0) {

    let ret = await TradeRecord.find({_id: {$in: tradids}})
    .select('device organization restaurant user deploySite consumeInterval amount mainAccountAmount subsidyAmount giveFreeAmount balance subsidyBalance giveFreeBalance tradeAt sn deviceSerial subAccount supermarketConsume payMethod consumeType consumePayMethod deviceMode ')
    .populate('organization', 'name')
    .populate('restaurant', 'name')
    .populate('deploySite', 'name')
    .populate({
    path: 'user',
    select: 'department name type jobNumber cardUid fingerprint',
    populate: {path: 'department', select: 'name'}
    })

    rowsbase.push(...ret)
    }
    }
    }

    代码如上
    617953997
        2
    617953997  
       2022-04-08 10:28:50 +08:00
    流式查询 + 流式写入
    yousabuk
        3
    yousabuk  
       2022-04-08 10:52:46 +08:00 via iPhone
    查完 1000 条,写文件,再查一下个 1000 条,写文件。

    再不行就每次 100 条,50 条……

    看不懂这个代码,但是小内存下处理就是这么个流程。
    micean
        4
    micean  
       2022-04-08 11:01:28 +08:00
    #3+1

    每查 1000 条写在 csv 尾部就行了
    paopjian
        5
    paopjian  
       2022-04-08 11:04:19 +08:00
    内存有限制写入 excel 是不是炸内存了,写成 csv 试一下?
    Dnlyao
        6
    Dnlyao  
    OP
       2022-04-08 11:11:08 +08:00
    流程是 let row =[] 先查询 1000 条数据 再 push 进 row ,再循环下去。未到写入文件,就爆内存了
    twing37
        7
    twing37  
       2022-04-08 11:27:56 +08:00
    有没有可能流程是 使用 stream, send -> limit buffer -> rev 呢?
    4771314
        8
    4771314  
       2022-04-08 11:30:38 +08:00
    分片处理或者使用 stream 的方式向 excel 中追加数据,最后将 Excel 导出,应该可以解决
    Dnlyao
        9
    Dnlyao  
    OP
       2022-04-08 11:48:05 +08:00
    感谢各位回复,我去尝试一下。
    INCerry
        10
    INCerry  
       2022-04-08 17:03:08 +08:00
    应该是要复用内存的
    Dnlyao
        11
    Dnlyao  
    OP
       2022-04-08 17:14:45 +08:00
    @INCerry 能详细说一下怎么处理吗?
    Dnlyao
        12
    Dnlyao  
    OP
       2022-04-08 17:26:47 +08:00
    用了 .cursor() eachAsync 还是不行,内存控制不住
    snoy
        13
    snoy  
       2022-04-09 16:50:34 +08:00
    姿势不对,我这个可以
    [email protected]:gogogo1024/mongodbStreamToCSV.git
    Dnlyao
        14
    Dnlyao  
    OP
       2022-04-11 10:14:53 +08:00
    @snoy 谢谢 我现在看看。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3774 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 10:36 · PVG 18:36 · LAX 03:36 · JFK 06:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.