経緯
node-postgresを使用してbulk insertする時に苦労したので、備忘録を残す。
実行環境
- linux
- nodejs
- postgres
性能比較
1行ずつのINSERTとの性能比較については、こちら(1000万件のINSERTを映画1本分ぐらい時間節約できた話)を参照。
postgres の準備
下記サイトを参考に node-js から postgres に接続する準備をする。
Node-Postgres
を使ったときに、試行錯誤してできた Postgres クラス
大量データを 1000 行単位に分ける
paramsにはINSERT時のパラメータを配列で格納しておく。
例
[
['001', 'hoge'],
['002', 'fuga'],
['003', 'piyo'],
]
※追記
上限1000件は他のSQL言語でした。
postgresのbulk insertは一度に1000件が上限とのことなので、 処理したいデータを1000件ずつ詰め直す。
※もっといい方法があれば教えてください。
const makeBulkArray = (params) => {
let bulkArray = [];
let remaining = params;
// 残り件数が1000より少なくなるまで
while (remaining.length > 1000) {
// postgresのバルクインサートは1000件が上限
let oneBulk = remaining.slice(0, 1000);
bulkArray.push(oneBulk);
// 処理配列に詰めたデータを取り除く
remaining = remaining.slice(1000);
}
// 残り件数が1000件より少ない場合の余りデータを最後に詰める
if (remaining.length > 0) bulkArray.push(remaining);
return bulkArray;
};
bulk insert する
参考にさせていただいたサイト(PostgreSQL に node-postgres モジュールを使って BULK INSERT をする方法)のとおりにやると、現在のpg-formatでは動かせないようで公式ドキュメントを見て調整した。
const format = require('pg-format');
const insertData = async (params) => {
// poolからクライアント接続
const pg = await getClient();
// pg-formatを使って、pgが実行できるSQLを生成
const sql = format('INSERT INTO test_table (id, name) VALUES %L', params);
await pg.query(sql); // SQL実行
await pg.release(); // クライアントをpoolに返す
};
insertData(bulkArray);