Golang:使用像 node.js 这样的可读流从 PostgreSQL 数据库中选择几百万行

vod*_*095 1 postgresql go node.js

我有一个约 5000 万行的 PostgreSQL 表,我想编写 Go 代码来从这个表中选择约 100 万行,并以有效的方式处理它们。

上一次我使用 nodejs 和这个 NPM 模块pg-query-stream来生成可读记录流,所以我可以像处理任何可读对象流一样处理它们。

在这里,我发布了用于处理数据的简化代码:


const pg = require('pg');
const QueryStream = require('pg-query-stream');

 
//pipe 1,000,000 rows to stdout without blowing up your memory usage
pg.connect((err, client, done) => {
  if (err) throw err;
  const query = new QueryStream('SELECT * FROM generate_series(0, $1) num', [1000000]);
  const stream = client.query(query);
  //release the client when the stream is finished
  stream.on('end', done);
  stream.on('data', function(data) { 
    stream.pause();
    funcDoSomethingWithDataAsync(data, function(error) {
      if(error) throw error;
      stream.resume();
    });
 };
})

Run Code Online (Sandbox Code Playgroud)

如何在 Go 中模拟可读的数据库记录流?Go 中的sql.Scanner是否可以像 nodejs 模块那样处理流式查询结果?

我已经有可以正常工作的优化查询,我只想将查询执行结果流式传输到 Go,就像它在 nodejs 库中所做的那样。

Sch*_*ern 8

是的,它的工作原理非常相似:执行查询,遍历结果。这是一个使用lib/pq的简单示例,它是database/sql的 Postgres 版本。

进行查询,然后遍历Rows

rows, err := db.Query(`SELECT * FROM generate_series(0, $1) num`, 1000000)
if err != nil {
   panic(err)
}
 
defer rows.Close()
for rows.Next() {
    var num int
 
    err = rows.Scan(&num)
    if err != nil {
       panic(err)
    }
 
    fmt.Println(num)
}
Run Code Online (Sandbox Code Playgroud)

  • 不,它有一个缓冲区来获取一些结果,以避免对每一行进行网络调用。尝试使用不同大小的系列并检查您的内存使用情况,它应该保持不变。 (6认同)