如何使用pg-promise在流中执行查询?

时间:2019-05-20 19:46:32

标签: node.js pg-promise

我正在尝试使用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 +上。

1 个答案:

答案 0 :(得分:0)

这是由于对Promise /异步代码的无效使用。

db.one('SELECT 1');行没有链接到任何东西,以很快的速度产生了松散的承诺,从而又污染了内存。

您需要使用.then.catchawait将其链接。