我正在尝试使用node.js app将我的mssql数据库中的900万条记录导出到mysql数据库
我遇到了一个内存问题,我怀疑是由于我的地图功能。(Bluebird Promise.map)
下面的Myfucntion()调用doThis()函数,它从我的Mssql数据库中获取一组记录,然后将记录插入到MySql数据库中。
Myfucntion(){
Promise.map(ids, id => doThis(id).then(results => console.log(results)), { concurrency: 5});
}
const doThis = async (id) => {
try{
const results = await sql.query`select results where id = ${id}`;
if((results && results.recordset) && results.recordset.length > 0 ) {
results.recordset.map(asset => insertResultslAsset(convertResultAsset(asset)));
}
}
catch(err){
console.log(err)
}
};
convertResultAsset(asset)函数在执行插入之前创建一个4属性对象。
我怀疑发生内存泄漏是因为转换后的资产以.map迭代的形式逐步存储在内存中
我能够通过在程序上运行--max-old-space-size = 20000来缓解这个问题。
从doThis()函数执行插入后,我无需存储转换后的Assets。
有没有办法从.map函数中释放这些对象?
答案 0 :(得分:1)
一个代码块中的async
和promises
太多了。另外,bluebird有内部错误处理程序挂钩,因此没有必要使用try-catch
块(可能,此块可能会降低性能,请参阅此文章:optimization-killers )
这是第一个简化版本:
const debug = require('debug')('my-app-name')
Myfucntion(){
return Promise.map(
ids,
id => doThis(id),
{ concurrency: 5}
)
}
function doThis(id) {
const results = sql.query('select results where id = ${id}');
if (
results &&
results.recordset &&
results.recordset.length > 0
) {
return results
.recordset
.map(asset => insertResultslAsset(convertResultAsset(asset)))
.then(res => debug(res))
.catch(err => debug('error', err);
}
return null
}
我删除了console.log
,bcz我不确定它的异步/同步性质,debug
模块可能在大多数情况下效果更好(但要查看其输出,您应该运行程序环境标志,如下所示:DEBUG=* nodejs app.js
)
我不确定100%问题是否已解决,因为还有两个未知函数:
insertResultslAsset
convertResultAsset
这些函数可能包含闭包和不必要的锁定变量吗?