sql >> Databáze >  >> RDS >> PostgreSQL

node-postgres s velkým množstvím dotazů

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ý:

  1. Rozdělte/omezte své vložky do více transakcí;
  2. Udržujte seznam vložek v jedné transakci na přibližně 10 000 záznamů;
  3. Provádějte všechny své transakce v synchronním řetězci.
  4. 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



  1. Rozdělte data do 3 sloupců

  2. Hledání největší skupiny po sobě jdoucích čísel v rámci oddílu

  3. MSDTC na serveru „server není k dispozici“

  4. Jak vytvořit VARRAY jako databázový objekt v databázi Oracle