如何从node.js快速将许多脚本生成的记录放入PostgreSQL中

How can I put many script-generated records in PostgreSQL quickly from node.js?

本文关键字:记录 PostgreSQL 脚本 许多 node js      更新时间:2023-09-26

下面的代码从node.js向PostgreSQL服务器插入了200000条记录,在我的笔记本电脑上花了大约17分钟,感觉非常慢。

var pg = require('pg');
var Client = pg.Client;
var async = require('async');
var client = new Client(connectionString);
client.connect();
var rollback = function(client) {
  client.query('ROLLBACK', function() {
    client.end();
    process.kill();
  });
};
client.query('BEGIN',function(err,result){
  if(err){ console.error(err); rollback(client);};
  async.waterfall([
    function(cb){
      client.query('DROP INDEX idx',function(err,result){
        client.query('TRUNCATE TABLE tbl',function(err,result){
          async.forEach(values,function(value,valueNext){
            client.query('INSERT INTO tbl ('
                         + 'col1,'
                         + 'col2) VALUES ($1,$2)',[
                           value,
                           generatedSomething(value)
                         ],function(err){
                           valueNext();
                         });
          },function(err,result){
            if(err){ console.error(err); rollback(client);cb(false);return;};
            client.query('CREATE INDEX idx ON tbl',function(err,result){
              cb(null);
            });
          });
        });
      });
    });
  },
],function(err){
  client.query('COMMIT', client.end.bind(client));
});

我采用了一些策略来加快速度。

  • 插入前删除所有索引,插入完成后创建索引。。。好的
  • 使用TRUNCATE TABLE而不是DELETE FROM。。。好的
  • 使用COPY FROM而不是INSERT INTO。。。未完成

使用COPY FROM而不是INSERT INTO似乎会产生效果,但它用于导入的CSV文件,而不是脚本生成的值。

那么,这是否意味着将脚本生成的值导出到临时CSV文件,并使用COPY FROM导入值,是将值快速插入PostgreSQL的最有效方法?

copyFrom将返回一个WritableStream,您可以将值附加为CSV,如:

var stream = client.copyFrom("COPY tbl (col1, col2) FROM STDIN WITH CSV");
stream.on('close', function() {
  client.query("COMMIT");
});
stream.on('error', rollback);
async.forEach(values, function(value, valueNext) {
  stream.write(value + "," + generatedSomething(value) + "'n");
});
stream.end();

当然,您需要正确地转义您的值