10,000,000 行を処理したい
これは私のコードです:
stmt.each('select * from very_big_table',function(err,rows,next){
console.log('This can take 2 seconds'
})
問題は、RAM をすべて使い果たしてしまうのか、それともハード ドライブから行ごとに読み取るのかということです。
10,000,000 行を処理したい
これは私のコードです:
stmt.each('select * from very_big_table',function(err,rows,next){
console.log('This can take 2 seconds'
})
問題は、RAM をすべて使い果たしてしまうのか、それともハード ドライブから行ごとに読み取るのかということです。
両方。statement.each
関数が高速で同期している場合は余分なメモリを使用しませんが、非同期関数を使用すると、ディスクからデータをロードできるのと同じ速さですべての非同期処理が開始され、RAM がすべて消費されます。
ここに投稿した問題でも言われているように、 https://github.com/mapbox/node-sqlite3/issues/686を使用して目的の動作を得ることができますStatement.get()
。Statement.get()
パラメータなしで次の行をフェッチします。したがって、次のように独自の非同期バージョンを実装できます。
function asyncEach(db, sql, parameters, eachCb, doneCb) {
let stmt;
let cleanupAndDone = err => {
stmt.finalize(doneCb.bind(null, err));
};
stmt = db.prepare(sql, parameters, err => {
if (err) {
return cleanupAndDone(err);
}
let next = err => {
if (err) {
return cleanupAndDone(err);
}
return stmt.get(recursiveGet);
};
// Setup recursion
let recursiveGet = (err, row) => {
if (err) {
return cleanupAndDone(err);
}
if (!row) {
return cleanupAndDone(null);
}
// Call the each callback which must invoke the next callback
return eachCb(row, next);
}
// Start recursion
stmt.get(recursiveGet);
});
}
組み込みの とは構文が少し異なりStatement.each
、エラーは最後のコールバックにのみ送信され、オプションのパラメーターはサポートされないことに注意してください。
また、これは通常のStatement.each
関数よりも遅いことに注意してください。複数の呼び出しを発行することで改善できるget
ため、呼び出されたときに次の行が待機しnext
ますが、そのコードをたどるのははるかに困難です。
スニペットの使用例:
let rowCount = 0;
asyncEach(db, 'SELECT * from testtable', [], (row, next) => {
assert.isObject(row);
rowCount++;
return next();
}, err => {
if (err) {
return done(err);
}
assert.equal(rowCount, TEST_ROW_COUNT);
done();
});