Dan*_*tyo 9 postgresql node.js node-postgres
我刚刚使用node-postgres开始使用postgres来使用node.js.我试图做的一件事就是写一个简短的js来填充我的数据库,使用一个包含大约200,000个条目的文件.
我注意到在一段时间后(少于10秒),我开始得到"错误:连接终止".我不确定这是否是我使用node-postgres的问题,或者是因为我是垃圾邮件postgres.
无论如何,这是一个显示此行为的简单代码:
var pg = require('pg');
var connectionString = "postgres://xxxx:xxxx@localhost/xxxx";
pg.connect(connectionString, function(err,client,done){
if(err) {
return console.error('could not connect to postgres', err);
}
client.query("DROP TABLE IF EXISTS testDB");
client.query("CREATE TABLE IF NOT EXISTS testDB (id int, first int, second int)");
done();
for (i = 0; i < 1000000; i++){
client.query("INSERT INTO testDB VALUES (" + i.toString() + "," + (1000000-i).toString() + "," + (-i).toString() + ")", function(err,result){
if (err) {
return console.error('Error inserting query', err);
}
done();
});
}
});
Run Code Online (Sandbox Code Playgroud)
它在大约18,000-20,000次查询后失败.这是使用client.query的错误方法吗?我尝试更改默认客户端号码,但似乎没有帮助.
client.connect()似乎也没有帮助,但那是因为我有太多客户端,所以我绝对认为客户端池是可行的方法.
谢谢你的帮助!
vit*_*y-t 13
UPDATE
这篇答案自此被本文取代:数据导入,代表了最新的方法.
为了复制您的场景,我使用了pg-promise库,我可以确认正在尝试它将永远不会工作,无论您使用哪个库,重要的方法都是如此.
下面是一个修改过的方法,我们将插入分区为块,然后在事务中执行每个块,这是负载平衡(也称为限制):
function insertRecords(N) {
return db.tx(function (ctx) {
var queries = [];
for (var i = 1; i <= N; i++) {
queries.push(ctx.none('insert into test(name) values($1)', 'name-' + i));
}
return promise.all(queries);
});
}
function insertAll(idx) {
if (!idx) {
idx = 0;
}
return insertRecords(100000)
.then(function () {
if (idx >= 9) {
return promise.resolve('SUCCESS');
} else {
return insertAll(++idx);
}
}, function (reason) {
return promise.reject(reason);
});
}
insertAll()
.then(function (data) {
console.log(data);
}, function (reason) {
console.log(reason);
})
.done(function () {
pgp.end();
});
Run Code Online (Sandbox Code Playgroud)
这在大约4分钟内产生了1000,000条记录,在前3次交易后大幅放缓.我使用的是Node JS 0.10.38(64位),它消耗了大约340MB的内存.这样我们连续10次插入100,000条记录.
如果我们这样做,只有这次在100个事务中插入10,000条记录,相同的1,000,000条记录仅在1m25s内添加,没有减速,Node JS消耗大约100MB的内存,这告诉我们像这样的分区数据非常好主意.
使用哪个库无关紧要,方法应该相同:
如果你违反了这些规则,你就会遇到麻烦.例如,如果您违反规则3,您的Node JS进程可能会快速耗尽内存并抛出错误.我的例子中的规则4由图书馆提供.
如果您遵循此模式,则无需使用连接池设置来解决问题.
更新1
更高版本的pg-promise完美支持这些场景,如下所示:
function factory(index) {
if (index < 1000000) {
return this.query('insert into test(name) values($1)', 'name-' + index);
}
}
db.tx(function () {
return this.batch([
this.none('drop table if exists test'),
this.none('create table test(id serial, name text)'),
this.sequence(factory), // key method
this.one('select count(*) from test')
]);
})
.then(function (data) {
console.log("COUNT:", data[3].count);
})
.catch(function (error) {
console.log("ERROR:", error);
});
Run Code Online (Sandbox Code Playgroud)
如果您不想包含任何额外的内容,例如表创建,那么它看起来更简单:
function factory(index) {
if (index < 1000000) {
return this.query('insert into test(name) values($1)', 'name-' + index);
}
}
db.tx(function () {
return this.sequence(factory);
})
.then(function (data) {
// success;
})
.catch(function (error) {
// error;
});
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅同步事务
Bluebird
例如,使用作为promise库,我的生产机器上需要1m43s来插入1,000,000条记录(没有启用长堆栈跟踪).
你只需要factory
根据你的方法返回请求index
,直到你没有离开,简单就是这样.
最好的部分,这不仅速度快,而且对NodeJS流程的负担也很小.在整个测试期间,内存测试过程保持在60MB以下,仅消耗7-8%的CPU时间.
更新2
从版本1.7.2开始,pg-promise轻松支持超大规模事务.请参见同步事务一章.
例如,我可以在家用电脑上在15分钟内在单个事务中插入10,000,000条记录,Windows 8.1为64位.
为了测试我将我的PC设置为生产模式,并使用Bluebird作为promise库.在测试期间,整个NodeJS 0.12.5进程(64位)的内存消耗不超过75MB,而我的i7-4770 CPU显示15%的负载.
以相同的方式插入100米记录需要更多的耐心,但不需要更多的计算机资源.
与此同时,先前对1m刀片的测试从1m43s下降到1m31s.
更新3
以下注意事项可以产生巨大的差异:性能提升.
更新4
相关问题,有一个更好的实现示例: 带有pg-promise的大规模插入.
更新5
可以在这里找到更好更新的示例:nodeJS将数据插入PostgreSQL错误
归档时间: |
|
查看次数: |
11304 次 |
最近记录: |