Node.js 具有大量查询的节点postgres
我刚刚开始使用node.js和postgres,使用node-postgres。我尝试做的一件事是编写一个简短的js来填充我的数据库,使用一个包含大约200000个条目的文件 我注意到过了一段时间(不到10秒),我开始收到“错误:连接终止”。我不确定这是我如何使用节点postgres的问题,还是因为我在滥发postgres 无论如何,这里有一个简单的代码显示了这种行为:Node.js 具有大量查询的节点postgres,node.js,postgresql,node-postgres,Node.js,Postgresql,Node Postgres,我刚刚开始使用node.js和postgres,使用node-postgres。我尝试做的一件事是编写一个简短的js来填充我的数据库,使用一个包含大约200000个条目的文件 我注意到过了一段时间(不到10秒),我开始收到“错误:连接终止”。我不确定这是我如何使用节点postgres的问题,还是因为我在滥发postgres 无论如何,这里有一个简单的代码显示了这种行为: var pg = require('pg'); var connectionString = "postgres://xxxx
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();
});
}
});
var pg=require('pg');
变量连接字符串=”postgres://xxxx:xxxx@本地主机/xxxx”;
pg.connect(连接字符串、函数(错误、客户端、完成){
如果(错误){
返回控制台。错误('无法连接到postgres',错误);
}
query(“如果存在testDB,则删除表”);
query(“创建表,如果不存在testDB(id int,first int,second int)”;
完成();
对于(i=0;i<1000000;i++){
query(“插入testDB值(“+i.toString()+”,“+(1000000-i).toString()+”,“+(-i.toString()+”),函数(err,result){
如果(错误){
返回控制台.error('插入查询时出错',err);
}
完成();
});
}
});
在大约18000-20000次查询后,它会失败。这是使用client.query的错误方法吗?我尝试更改默认的客户机号码,但似乎没有帮助
client.connect()似乎也没有什么帮助,但那是因为我有太多的客户端,所以我肯定认为客户端池是一种方法
谢谢你的帮助 我猜您正在达到最大池大小。由于
client.query
是异步的,所以在返回所有可用的连接之前,都会先使用它们
默认池大小为10。请点击此处:
通过设置pg.defaults.poolSize
,可以增加默认池大小:
pg.defaults.poolSize = 20;
更新:释放连接后执行另一个查询
var pg = require('pg');
var connectionString = "postgres://xxxx:xxxx@localhost/xxxx";
var MAX_POOL_SIZE = 25;
pg.defaults.poolSize = MAX_POOL_SIZE;
pg.connect(connectionString, function(err,client,done){
if(err) {
return console.error('could not connect to postgres', err);
}
var release = function() {
done();
i++;
if(i < 1000000)
insertQ();
};
var insertQ = function() {
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);
}
release();
});
};
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 < MAX_POOL_SIZE; i++){
insertQ();
}
});
var pg=require('pg');
变量连接字符串=”postgres://xxxx:xxxx@本地主机/xxxx”;
var MAX_POOL_SIZE=25;
pg.defaults.poolSize=最大池大小;
pg.connect(连接字符串、函数(错误、客户端、完成){
如果(错误){
返回控制台。错误('无法连接到postgres',错误);
}
var release=function(){
完成();
i++;
如果(i<1000000)
insertQ();
};
var insertQ=函数(){
query(“插入testDB值(“+i.toString()+”,“+(1000000-i).toString()+”,“+(-i.toString()+”),函数(err,result){
如果(错误){
返回控制台.error('插入查询时出错',err);
}
释放();
});
};
query(“如果存在testDB,则删除表”);
query(“创建表,如果不存在testDB(id int,first int,second int)”;
完成();
对于(i=0;i
其基本思想是,由于您正在以相对较小的连接池大小将大量查询排队,因此您将达到最大池大小。这里,我们仅在释放现有连接后进行新查询。更新 此后,这一答案被本文取代,它代表了最新的方法
为了复制您的场景,我使用了库,并且我可以确认,正面尝试永远不会奏效,无论您使用哪个库,重要的是方法 下面是一种改进的方法,我们将插入划分为块,然后在事务中执行每个块,这就是负载平衡(也称为节流):
函数插入记录(N){
返回db.tx(函数(ctx){
var查询=[];
对于(变量i=1;i=9){
回报承诺。决心(“成功”);
}否则{
返回insertAll(++idx);
}
},功能(原因){
退回承诺。拒绝(理由);
});
}
insertAll()
.then(功能(数据){
控制台日志(数据);
},功能(原因){
控制台日志(原因);
})
.done(函数(){
pgp.end();
});
这在大约4分钟内产生了1000000条记录,在前3次事务处理后,速度大大减慢。我使用的是节点JS 0.10.38(64位),它消耗了大约340MB的内存。这样我们插入了100000条记录,连续10次
如果我们也这样做,这次只在100个事务中插入10000条记录,同样的1000000条记录只需1m25s就可以添加,速度不会减慢,节点JS消耗了大约100MB的内存,这告诉我们,像这样划分数据是一个非常好的主意
无论您使用哪个库,方法都应该相同:
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);
});
功能工厂(索引){
如果(索引<1000000){
返回此.query('insert into test(name)values($1)','name-'+索引);
}
}
db.tx(函数(){
退回此批([
this.none('drop table if exists test'),
this.none('创建表测试(id序列,名称文本)'),
this.sequence(factory),//键方法
这个.one('select count(*)from test')
]);
})
.then(功能(数据){
log(“计数:”,数据[3]。计数);
})
.catch(函数(错误){
日志(“错误:”,错误);
});
<
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;
});