2016-01-29 3 views
0

У меня есть сценарий ETL-узла, который импортирует большое количество записей (где-то к северу от 1 миллиона) в ~ 1000 партиях из 1000 предметов. Для этого он:Недостаточно памяти Импорт большого набора данных

  1. Запросит первую партию. Это обеспечивает первые 1000 пунктов и сообщает нам, сколько партий нам нужно импортировать, и общее количество доступных нам записей.
  2. Импортирует первую партию из 1000 записей.
  3. Итерации по каждой дополнительной партии и импорт записей в эту партию.

Проблема в том, что у меня заканчивается память после обработки ~ 80 партий (менее 10%!), И я думаю, что это проблема с тем, как я структурировал код. Как будто что-то накапливается за кулисами, и я потерял все возможности распознать его. Вот базовый код:

getBatch(1) 
    .each(function(item, i, total) { // always 1000 iterations 
     return save(item); 
    }) 
    .then(function() { 
     // Return an array of batch numbers left to be imported 
     // In this case, batches 2 through ~1000. The totalBatches value 
     // is saved to an in-scope variable within the getFirstBatch() 
     // function. 
     return Array.from(new Array(totalBatches - 1).keys(), x => x + 2); 
    }) 
    .each(function(batchNumber, i, batchCount) { // Just over 1000 iterations 
     return getBatch(batchNumber) 
      .each(function(item, i, total) { // Always 1000 iteractions until the last batch 
       return save(item); 
      }); 
    }) 
    .tap(function(importedBatchNumbers) { // Not even close to getting here 
     // Do a few minor cleanup operations 
    }) 
    .then(function(importedBatchNumbers) { 
     // Summarize 
     totalBatchesImported = importedBatchNumbers.length + 1; 

     console.log('...'); 
    }) 

Возможно, есть лучший способ приблизиться к этому, что я не рассматривал? Я использую библиотеку bluebird для обещаний и Knex для обработки активности базы данных.

На данный момент все, что я действительно знаю, это то, что я даже не близко. Работа выполнена правильно, но этого недостаточно. Любые предложения были бы очень оценены.

+0

В чем разница между (1) "1000 пунктов" и (2) "1000 записей"? –

+0

@ Roamer-1888: "records" = "items". Извиняюсь, если я не согласен с терминологией. –

+0

Возможно, вы просто жертва ленивого GC. Если это так, то введение некоторой искусственной задержки может дать GC возможность сделать свое дело. –

ответ

0

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

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

Для таких больших наборов данных можно обращаться с помощью Stream.

Вы также можете использовать библиотеки chunk the data for you

+0

Хммм. Знаешь, я, возможно, не думаю об этом правильно. Я думал (и мой вывод, похоже, указывает), что партии (и элементы в каждой партии) обрабатываются последовательно. –

Смежные вопросы