【发布时间】:2016-01-30 02:44:27
【问题描述】:
我有一个节点 ETL 脚本,它可以在大约 1000 批 1000 项中导入大量记录(大约 100 万条)。为此,它:
- 请求第一批。这提供了前 1000 个项目,并告诉我们需要导入多少批次以及我们可用的记录总数。
- 导入第一批 1000 条记录。
- 迭代每个其他批次并导入该批次中的记录。
问题是我在处理了大约 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 来处理数据库活动。
在这一点上,我真正知道的是我什至还没有接近。工作做得很好,但还远远不够。任何建议将不胜感激。
【问题讨论】:
-
(1)“1000条”和(2)“1000条记录”有什么区别?
-
@Roamer-1888:“记录”=“项目”。如果我与术语不一致,请道歉。
-
您可能只是惰性 GC 的受害者。如果是这样,那么引入一些人为的延迟可能会让 GC 有机会做它的事情。
-
另一个想法——
getBatch()和/或save()抓取需要释放的资源(例如数据库连接)?
标签: node.js promise bluebird knex.js