【问题标题】:How to execute queries during a stream using pg-promise?如何使用 pg-promise 在流期间执行查询?
【发布时间】:2019-05-22 21:23:59
【问题描述】:

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

到达第 60000 行需要 10 多分钟。

更新:

我编辑了上面的代码以包含 async/await 以等待内部查询完成,并将系列增加到 10,000,000。我使用 512MB 内存运行节点进程,当接近该限制时程序明显变慢但不会崩溃。这个问题出现在 v10 而不是 v11+ 的节点上。

【问题讨论】:

  • 您确定是额外的行db.one('SELECT 1'); 导致了额外的内存使用,而不是其他原因吗?另外,.then.catch 在哪里?没有,这是一个松散的承诺。
  • 又看了一遍,马上就发现了问题。我不是在等待内部查询完成。添加 async/await 修复了它。我的完整应用程序中仍然存在内存泄漏以及许多其他逻辑,所以我会看看是否可以将其简化为简单的内容并在此处发布。

标签: node.js pg-promise


【解决方案1】:

这是由于无效使用承诺/异步代码造成的。

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

您需要使用.then.catchawait 链接它。

【讨论】:

  • 感谢您的快速回答。我已根据您的建议更新了问题。
猜你喜欢
  • 1970-01-01
  • 2020-08-03
  • 2020-10-21
  • 2019-11-30
  • 2021-02-04
  • 2017-10-14
  • 2019-01-04
  • 2018-02-01
  • 2018-02-19
相关资源
最近更新 更多