Sqlite データベースから膨大な量 (5 ~ 12 百万行) のアーカイブ データを取得して csv ファイルにエクスポートしたいと考えています。これを行っている間、サーバー全体がブロックされます。サーバーは他の接続を処理できません (たとえば、ブラウザーの別のタブで Web サイトを開くことができませんでした)。
Node.JS サーバー部分:
function exportArchiveData(response, query){
response.setHeader('Content-type', 'text/csv');
response.setHeader('Content-disposition', 'attachment; filename=archive.csv');
db.fetchAllArchiveData(
query.ID,
function(error, data){
if(!error)
response.write(data.A + ';' + data.B + ';' + data.C + '\n');
},
function(error, retrievedRows){
response.end();
});
};
SQLite DB モジュール:
module.exports.SS.prototype.fetchAllArchiveData = function (
a, callback, complete) {
var self = this;
// self.sensorSqliteDb.all(
self.sensorSqliteDb.each(
'SELECT A, B, C '+
'FROM AD WHERE '+
' A="' + a + '"'+
' ORDER BY C ASC' +
';'
,
callback,
complete
);
};
CREATE INDEX IAD ON AD(A, C) のように AD にインデックスも作成し、EXPLAIN QUERY PLAN は、このインデックスが sqlite エンジンによって使用されていることを示しています。
それでも、exportArchiveData サーバーを呼び出すと、データは適切に送信されますが、その間は他のアクションを実行できません。膨大な量のデータ (送信する行数が 5 ~ 1200 万行) があるため、3 分ほどかかります。
これがサーバー全体をブロックするのを防ぐにはどうすればよいですか?
EACHを使用し、コールバックがあると、サーバーの応答性が向上すると思いました。また、メモリ使用量が膨大です (約 3GB 以上)。どうにかしてこれを防ぐことはできますか?
コメントへの回答として、いくつかの説明を追加したいと思います。
developmentseed の node-sqlite3を使用しています。非同期でノンブロッキングでなければなりません。そしてそうです。声明が準備されたら、メインページをリクエストできます。しかし、サーバーがデータの提供を開始すると、Node.js サーバーがブロックされます。ホームページのリクエストは、コールバックを呼び出すための1つのリクエストであり、アーカイブデータ「各」を処理するコールバックのリクエストは無数にあるためだと思います。
Linux コマンド ラインから sqlite3 ツールを使用すると、すぐに行を取得できませんが、node-sqlite3 が非ブロッキングである限り、それは問題ではありません。
はい。私はCPU最大に達しています。さらに悪いことに、2 倍のデータを要求すると、メモリ全体が使用され、サーバーが永久にフリーズします。