我正在尝试从mysql
数据库中查询400k行,一次获取10个。要异步执行此操作,我需要使用这样的递归:
var migrate = function(offset, size) {
Mysql.query(query, [offset, size], function(err, rows) {
if (!err && rows.length) {
setTimeout(function() {
// Pretend doing something and get next batch.
migrate(offset + size, size);
}, 1000);
}
});
};
migrate(0, 10);
问题是,migrate()
的第一次调用会创建一个自己的子回调,并且所有这些回调都会留在内存中,直到最后migrate()
完成。
想到的唯一解决方案是在while
循环中同步运行它。
请告知您如何正确地做到这一点?感谢。
答案 0 :(得分:0)
在使用mysql模块的当前示例中,可以通过查询所有记录而不进行分块并使用Streaming query rows来完成。一旦处理完结果,它将逐个运行查询。
Mysql.query(sql).on('result', function(row) {
Mysql.pause();
setTimeout(function() {
// Pretend doing something.
Mysql.resume();
}, 1000);
});
但是(!),result
回调不应该有任何闭包变量,因为在这种情况下这些变量将保留内存。我做了一些基准测试,这是我对它的了解,否则无法解释。
一般来说,如果你需要处理大量数据,无论是mysql还是其他什么都没关系,我建议:
答案 1 :(得分:0)
看看SynJS - 它允许同步运行javascript代码:
var SynJS = require('synjs');
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'tracker',
password : 'tracker123',
database : 'tracker'
});
function myMigrate(modules,connection) {
for(var i=0; i<4; i++) {
connection.query("SELECT CONCAT('processing data batch #',?) as res",[i], function(err, rows, fields) {
if (err) throw err;
console.log(i,rows[0].res);
modules.SynJS.resume(_synjsContext);
});
SynJS.wait();
}
};
var modules = {
SynJS: SynJS,
mysql: mysql,
};
SynJS.run(myMigrate,null,modules,connection,function () {
console.log('done');
});
结果将是:
0 'processing data batch #0'
1 'processing data batch #1'
2 'processing data batch #2'
3 'processing data batch #3'
done