AKTUALIZACE
Tato odpověď byla od té doby nahrazena tímto článkem:Importy dat , což představuje nejaktuálnější přístup.
Abych replikoval váš scénář, použil jsem pg-promise knihovnu a mohu potvrdit, že vyzkoušení z hlavy nikdy nebude fungovat, bez ohledu na to, kterou knihovnu používáte, záleží na přístupu.
Níže je upravený přístup, kdy rozdělujeme vkládání do bloků a poté provádíme každý blok v rámci transakce, což je vyvažování zátěže (neboli omezování):
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();
});
To vytvořilo 1 000 000 záznamů za přibližně 4 minuty, což se dramaticky zpomalilo po prvních 3 transakcích. Používal jsem Node JS 0.10.38 (64-bit), který spotřeboval asi 340 MB paměti. Tímto způsobem jsme vložili 100 000 záznamů 10krát za sebou.
Pokud uděláme totéž, pouze tentokrát vložíme 10 000 záznamů do 100 transakcí, stejných 1 000 000 záznamů se přidá za pouhých 1 m25 s, žádné zpomalení, s Node JS spotřebovává kolem 100 MB paměti, což nám říká, že rozdělení dat na oddíly je velmi dobrý nápad.
Nezáleží na tom, kterou knihovnu používáte, přístup by měl být stejný:
- Rozdělte/omezte své vložky do více transakcí;
- Udržujte seznam vložek v jedné transakci na přibližně 10 000 záznamů;
- Provádějte všechny své transakce v synchronním řetězci.
- Po provedení COMMIT každé transakce uvolněte připojení zpět k fondu.
Pokud některá z těchto pravidel porušíte, máte zaručeně potíže. Pokud například porušíte pravidlo 3, vašemu procesu Node JS pravděpodobně rychle dojde paměť a vyvolá chybu. Pravidlo 4 v mém příkladu poskytla knihovna.
A pokud se budete řídit tímto vzorem, nemusíte se obtěžovat s nastavením fondu připojení.
AKTUALIZACE 1
Pozdější verze pg-promise takové scénáře dokonale podporují, jak je ukázáno níže:
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);
});
a pokud nechcete zahrnout nic extra, například vytváření tabulek, vypadá to ještě jednodušeji:
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;
});
Viz Synchronní transakce pro detaily.
Pomocí Bluebird
jako slibová knihovna například trvá 1 m43s na mém produkčním stroji, než vložím 1 000 000 záznamů (bez povolených trasování dlouhého zásobníku).
Měli byste jen svou factory
požadavky na návrat metody podle index
, dokud vám nic nezbyde, takhle jednoduše.
A nejlepší na tom je, že to není jen rychlé, ale také to málo zatěžuje váš proces NodeJS. Proces testování paměti zůstává během celého testu pod 60 MB a spotřebovává pouze 7–8 % času CPU.
AKTUALIZACE 2
Počínaje verzí 1.7.2 pg-promise snadno podporuje supermasivní transakce. Viz kapitola Synchronní transakce .
Mohl bych například vložit 10 000 000 záznamů v jediné transakci za pouhých 15 minut na svém domácím počítači s Windows 8.1 64bit.
Pro test jsem nastavil svůj počítač do produkčního režimu a použil Bluebird jako příslibová knihovna. Během testu spotřeba paměti nepřesáhla 75 MB pro celý proces NodeJS 0.12.5 (64bitový), zatímco můj procesor i7-4770 vykazoval konzistentní 15% zatížení.
Vkládání 100m záznamů stejným způsobem by vyžadovalo jen více trpělivosti, ale ne více počítačových zdrojů.
Mezitím předchozí test pro 1m vložek klesl z 1m43s na 1m31s.
AKTUALIZACE 3
Následující úvahy mohou znamenat obrovský rozdíl:Zvýšení výkonu .
AKTUALIZACE 4
Související otázka s lepším příkladem implementace:Masivní vložky s pg-promise .
AKTUALIZACE 5
Lepší a novější příklad najdete zde:nodeJS vkládání dat do chyby PostgreSQL