我正在尝试使用pg-promise和pg-query-stream对查询流的每一行执行插入查询。使用我的方法,执行每个查询都会增加内存使用量。
我还将问题缩小到只在流中执行任何查询,而不仅仅是插入。我目前在流上侦听“数据”事件,暂停流,执行查询,然后恢复流。我也尝试过将查询流传递到执行查询的可写流中,但是却收到错误消息,指出数据库连接已关闭。
let count = 0;
const startTime = new Date();
const qs = new QueryStream('SELECT 1 FROM GENERATE_SERIES(1, 1000000)');
db.stream(qs, stream => {
stream.on('data', async () => {
count++;
stream.pause();
await db.one('SELECT 1');
if (count % 10000 === 0) {
const duration = Math.round((new Date() - startTime) / 1000);
const mb = Math.round(process.memoryUsage().heapUsed/1024/1024);
console.log(`row ${count}, ${mb}MB, ${duration} seconds`);
}
stream.resume();
});
});
我希望内存使用量徘徊在恒定值附近,但是输出看起来像以下内容:
row 10000, 105MB, 4 seconds
row 20000, 191MB, 6 seconds
row 30000, 278MB, 9 seconds
row 40000, 370MB, 10 seconds
row 50000, 458MB, 14 seconds
到达600000行需要10分钟以上。
更新:
我编辑了上面的代码,以包括async / await等待内部查询完成,然后将序列数增加到10,000,000。我使用512MB内存运行节点进程,并且在达到该限制时程序会显着降低速度,但不会崩溃。此问题发生在节点的v10而不是v11 +上。
答案 0 :(得分:0)
这是由于对Promise /异步代码的无效使用。
第db.one('SELECT 1');
行没有链接到任何东西,以很快的速度产生了松散的承诺,从而又污染了内存。
您需要使用.then.catch
或await
将其链接。