Nodejs: пакетная вставка большого количества строк в базу данных

Я хочу обработать большое количество записей (> 400 000) в пакете и вставить их в базу данных.

Я знаю, как перебирать массив с помощью for() или underscore.each(), а также знаю, как асинхронно вставлять запись в различные базы данных SQL (без SQL). Проблема не в этом, проблема в том, что я не могу найти способ сделать и то, и другое одновременно.

Само распределение базы данных здесь роли не играет, принцип применим для любой базы данных (NO)SQL с асинхронным интерфейсом.

Я ищу шаблон для решения следующей проблемы:

Циклический подход:

var results = []; //imagine 100k objects here
_.each(results,function(row){
  var newObj = prepareMyData(row);

  db.InsertQuery(newObj,function(err,response) {
    if(!err) console.log('YAY, inserted successfully');
  });

});

Такой подход явно ошибочен. Это как бы забивает базу данных запросами на вставку, не дожидаясь завершения ни одного из них. Говоря об адаптерах MySQL, использующих пул соединений, вы довольно скоро исчерпаете соединения, и скрипт выйдет из строя.

Рекурсивный подход:

var results = []; //again, full of BIGDATA ;)
var index = 0;
var myRecursion = function()
{
  var row = results[index];
  var data = prepareMyData(row);
  db.InsertQuery(data,function(err, response)
  {
    if (!err)
    {

    console.log('YAY, inserted successfully!');
    index++; //increment for the next recursive call of:
    if (index < results.length) myRecursion();
    }
  }
}
myRecursion();

В то время как этот подход работает довольно хорошо для небольших фрагментов данных (хотя он может быть медленным, но это нормально. цикл событий может некоторое время отдыхать, ожидая завершения запроса), он не работает для больших массивов - слишком много рекурсий .

Я мог бы легко написать пакетную вставку на любом другом процедурном языке, таком как PHP или около того, но я не хочу. Я хочу решить это асинхронно в nodejs - в образовательных целях.

Какие-либо предложения?


person Steffen    schedule 27.01.2014    source источник


Ответы (1)


Я нашел решение, которое работает для меня, но мне все еще интересно понять, как это работает технически.

Читая документы node-async, я нашел несколько функций для достижения этой цели:

async.map // перебирает массив

async.each//итерации по массиву параллельно

async.eachSeries //последовательно перебирает массив

async.eachLimit //выполняет итерацию по массиву параллельно с n (предельными) параллельными вызовами.

Например:

var results = []; //still huge array
// "4" means, async will fire the iterator function up to 4 times in parallel
async.eachLimit(results,4,function(row,cb){
  var data = prepareMyData(row);
  db.InsertQuery(data,function(err, response)
  {
    if (!err)
    {
        cb(err,response);
    }
  }
},function(err,res)
{
    console.log('were done!');
});
person Steffen    schedule 28.01.2014
comment
Можете ли вы предоставить пример кода, который делает вставки? - person Wexoni; 15.04.2016