PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

node-postgres с огромно количество заявки

АКТУАЛИЗАЦИЯ

Оттогава този отговор е заменен с тази статия:Импортиране на данни , което представлява най-актуалния подход.

За да репликирам вашия сценарий, използвах 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();
    });

Това доведе до 1 000 000 записа за около 4 минути, драматично забавяне след първите 3 транзакции. Използвах Node JS 0.10.38 (64-битов), който консумираше около 340MB памет. По този начин вмъкнахме 100 000 записа, 10 пъти подред.

Ако направим същото, само че този път вмъкнем 10 000 записа в рамките на 100 транзакции, същите 1 000 000 записа се добавят само за 1m25s, без забавяне, като Node JS консумира около 100 MB памет, което ни казва, че разделянето на данни като това е много добра идея.

Няма значение коя библиотека използвате, подходът трябва да е един и същ:

  1. Разпределете/ускорете вашите вмъквания в множество транзакции;
  2. Поддържайте списъка с вмъквания в една транзакция на около 10 000 записа;
  3. Изпълнете всичките си транзакции в синхронна верига.
  4. Освободете връзката обратно към пула след COMMIT на всяка транзакция.

Ако нарушите някое от тези правила, имате гарантирани проблеми. Например, ако нарушите правило 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);
    });

и ако не искате да включвате нищо допълнително, като създаване на таблица, тогава изглежда още по-просто:

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;
    });

Вижте Синхронни транзакции за детайли.

Използване на Bluebird като обещаващата библиотека, например, отнема 1m43s на моята производствена машина, за да вмъкна 1 000 000 записа (без активирани дълги следи на стека).

Просто ще имате своята factory метод връща заявки според index , докато не ви остане нищо, толкова просто.

И най-хубавото е, че това не само е бързо, но и създава малко натоварване на вашия NodeJS процес. Процесът на тестване на паметта остава под 60 MB по време на целия тест, като отнема само 7-8% от времето на процесора.

АКТУАЛИЗАЦИЯ 2

Започвайки с версия 1.7.2, pg-promise поддържа супер масивни транзакции с лекота. Вижте глава Синхронни транзакции .

Например, мога да вмъкна 10 000 000 записа в една транзакция само за 15 минути на моя домашен компютър с Windows 8.1 64-bit.

За теста настроих компютъра си в производствен режим и използвах Bluebird като обещаната библиотека. По време на теста потреблението на памет не надхвърли 75MB за целия процес NodeJS 0.12.5 (64-битов), докато моят процесор i7-4770 показа постоянни 15% натоварване.

Вмъкването на 100 милиона записи по същия начин би изисквало повече търпение, но не и повече компютърни ресурси.

Междувременно предишният тест за 1m вложки спадна от 1m43s на 1m31s.

АКТУАЛИЗАЦИЯ 3

Следните съображения могат да направят огромна разлика:Повишаване на производителността .

АКТУАЛИЗАЦИЯ 4

Свързан въпрос с по-добър пример за внедряване:Масивни вмъквания с pg-promise .

АКТУАЛИЗАЦИЯ 5

По-добър и по-нов пример може да се намери тук:nodeJS вмъкване на данни в PostgreSQL грешка



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. @@Fetch_status в postgreSQL

  2. ST_HexagonGrid geom вектор за намиране на всички точки

  3. Трябва ли да изтрия полето за идентификатор по подразбиране, когато използвам низов първичен ключ в Rails / Postgres?

  4. PostgreSQL multi INSERT...RETURNING с множество колони

  5. postgresql - задействане, актуализиране на времеви печат при актуализация на полето