我有一个节点ETL脚本,可以在大约1000个1000个项目中导入大量记录(在100万以北的某个地方)。为此,它:
问题是我处理了大约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库进行promises,使用Knex来处理数据库活动。
在这一点上,我真正知道的是我甚至都不亲近。工作做得很好,但远不够。任何建议都将非常感谢。
答案 0 :(得分:0)
您的示例似乎并未考虑任何类型的异步过程。正如我所知道的那样,一旦运行,它将立即尝试处理所有1000个批次,当它不能同时进行时(~80),它会被废弃。
在开始加载下一个批次之前,您需要确保每个批次实际上已完成处理。
使用Stream可以很好地处理像这样的大型数据集。
您还可以使用库chunk the data for you