Nodejs 请问一下,查询万条数据,内存不断增长的解决方法。
Nodejs 请问一下,查询万条数据,内存不断增长的解决方法。
node+mongoose ,利用 pm2 管理项目,内存限制 512MB 。业务是查询记录,然后导出 excel 。目前是手动将万条数据 id ,1000 条一组跑循环查询,放入数组,最后拿数组生成文件。但每次都内存超出,项目重启了。
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中处理大量数据查询时,内存不断增长的问题通常源于数据未得到妥善处理或未及时释放。以下是一些有效的解决方法:
-
流式处理: 使用流式处理(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(); });
-
分页查询: 将大数据集分成小块,分页查询。这可以通过在SQL查询中使用
LIMIT
和OFFSET
实现。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 } })();
-
使用外部存储: 如果数据量特别大,考虑将数据写入外部存储(如文件系统、数据库等),然后逐步处理。
通过上述方法,你可以有效控制Node.js应用在处理大量数据时的内存增长。