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

发布于 1周前 作者 phonegap100 来自 nodejs/Nestjs

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

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

15 回复

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)
}
}
}

代码如上


流式查询 + 流式写入

查完 1000 条,写文件,再查一下个 1000 条,写文件。

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

看不懂这个代码,但是小内存下处理就是这么个流程。

#3+1

每查 1000 条写在 csv 尾部就行了

内存有限制写入 excel 是不是炸内存了,写成 csv 试一下?

流程是 let row =[] 先查询 1000 条数据 再 push 进 row ,再循环下去。未到写入文件,就爆内存了

有没有可能流程是 使用 stream, send -> limit buffer -> rev 呢?

分片处理或者使用 stream 的方式向 excel 中追加数据,最后将 Excel 导出,应该可以解决

感谢各位回复,我去尝试一下。

应该是要复用内存的

能详细说一下怎么处理吗?

用了 .cursor() eachAsync 还是不行,内存控制不住

姿势不对,我这个可以
[email protected]:gogogo1024/mongodbStreamToCSV.git

谢谢 我现在看看。

在Node.js中处理大量数据查询时,内存不断增长的问题通常源于数据未得到妥善处理或未及时释放。以下是一些有效的解决方法:

  1. 流式处理: 使用流式处理(streaming)可以显著减少内存占用。Node.js的流允许你逐块处理数据,而不是一次性加载所有数据到内存中。

    const { Pool } = require('pg');
    const pool = new Pool();
    
    const client = await pool.connect();
    const query = 'SELECT * FROM your_table';
    
    const stream = client.query(query);
    stream.on('data', (row) => {
        // 处理每一行数据
        console.log(row);
    });
    stream.on('end', () => {
        client.release();
    });
    
  2. 分页查询: 将大数据集分成小块,分页查询。这可以通过在SQL查询中使用LIMITOFFSET实现。

    let offset = 0;
    const limit = 1000;
    
    async function fetchData() {
        const query = `SELECT * FROM your_table LIMIT $1 OFFSET $2`;
        const result = await pool.query(query, [limit, offset]);
        offset += limit;
        return result.rows;
    }
    
    (async () => {
        while (true) {
            const rows = await fetchData();
            if (rows.length === 0) break;
            // 处理rows
        }
    })();
    
  3. 使用外部存储: 如果数据量特别大,考虑将数据写入外部存储(如文件系统、数据库等),然后逐步处理。

通过上述方法,你可以有效控制Node.js应用在处理大量数据时的内存增长。

回到顶部