Nodejs: Пакетная вставка большого количества строк в базу данных
Я хочу обработать большое количество записей (>400 КБ) в пакете и вставить их в базу данных.
Я знаю, как перебирать массив с for() или underscore.each(), а также я знаю, как асинхронно вставлять записи в различные (не) базы данных SQL. Это не проблема - проблема в том, что я не могу придумать, как сделать то и другое одновременно.
Само распределение базы данных здесь не играет роли, этот принцип применим для любой (НЕТ) базы данных 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 - для образовательных целей.
Какие-либо предложения?
1 ответ
Я нашел решение, которое работает для меня, но мне все еще интересно понять, как это работает технически.
Читая документы по асинхронным узлам, я нашел несколько функций для достижения этой цели:
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!');
});