我正在使用pg-promise,我希望对一个表进行多次插入。我已经看到了Multi-row insert with pg-promise和How do I properly insert multiple rows into PG with node-postgres?之类的解决方案,我可以使用pgp.helpers.concat来连接多个选择。
但是现在,我需要在表格中插入大量的测量数据,记录超过10,000条,并且在https://github.com/vitaly-t/pg-promise/wiki/Performance-Boost中说: "你可以连接多少条记录 - 取决于记录的大小,但我绝不会用这种方法超过10,000条记录。因此,如果您需要插入更多记录,您可能希望将它们拆分为这样的连续批处理,然后逐个执行它们。"
我阅读了所有文章,但我无法弄清楚如何"分裂"我插入批处理,然后逐个执行。
谢谢!
答案 0 :(得分:1)
我认为天真的方法会起作用。
尝试将数据拆分为10,000条或更少的多条记录。 我会尝试使用此post的解决方案来拆分数组。
然后,多行插入每个数组pg-promise并在事务中逐个执行。
编辑:感谢@ vitaly-t精彩的图书馆和改善我的答案。
另外,不要忘记将查询包装在事务中,否则它 将消耗连接。
为此,请使用pg-promise中的batch函数异步解析所有查询:
// split your array here to get splittedData
int i = 0
var cs = new pgp.helpers.ColumnSet(['col_a', 'col_b'], {table: 'tmp'})
// values = [..,[{col_a: 'a1', col_b: 'b1'}, {col_a: 'a2', col_b: 'b2'}]]
let queries = []
for (var i = 0; i < splittedData.length; i++) {
var query = pgp.helpers.insert(splittedData[i], cs)
queries.push(query)
}
db.tx(function () {
this.batch(queries)
})
.then(function (data) {
// all record inserted successfully !
}
.catch(function (error) {
// error;
});
答案 1 :(得分:1)
<强>更新强>
最好是阅读以下文章:Data Imports。
作为pg-promise的作者,我不得不最终为这个问题提供正确的答案,因为之前发表的一篇并没有真正公正。
为了插入大量/无限数量的记录,您的方法应该基于方法sequence,这可以在任务和事务中使用。
var cs = new pgp.helpers.ColumnSet(['col_a', 'col_b'], {table: 'tableName'});
// returns a promise with the next array of data objects,
// while there is data, or an empty array when no more data left
function getData(index) {
if (/*still have data for the index*/) {
// - resolve with the next array of data
} else {
// - resolve with an empty array, if no more data left
// - reject, if something went wrong
}
}
function source(index) {
var t = this;
return getData(index)
.then(data => {
if (data.length) {
// while there is still data, insert the next bunch:
var insert = pgp.helpers.insert(data, cs);
return t.none(insert);
}
// returning nothing/undefined ends the sequence
});
}
db.tx(t => t.sequence(source))
.then(data => {
// success
})
.catch(error => {
// error
});
从性能的角度和负载限制,这是向数据库中插入大量行的最佳方法。
您所要做的就是根据应用程序的逻辑实现您的函数getData
,即基于序列index
的大数据来源,返回大约1,000 - 一次10,000个对象,具体取决于对象的大小和数据可用性。
另见一些API示例:
相关问题:node-postgres with massive amount of queries。
如果您需要获取所有插入记录的生成id-s,您可以按如下方式更改两行:
// return t.none(insert);
return t.map(insert + 'RETURNING id', [], a => +a.id);
和
// db.tx(t => t.sequence(source))
db.tx(t => t.sequence(source, {track: true}))
要小心,因为在内存中保留太多记录id会导致过载。