gpt4 book ai didi

performance - 为什么要从 Node.JS 的 sqlite block 中获取数据?

转载 作者:太空宇宙 更新时间:2023-11-03 22:18:00 26 4
gpt4 key购买 nike

我想从 Sqlite 数据库获取大量(5 - 1200 万行)存档数据并将其导出到 csv 文件。执行此操作时,整个服务器都会被阻止。服务器无法处理其他连接(例如我无法在浏览器的另一个选项卡中打开网站)。

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 数据库模块:

 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
);
};

我还在 AD 上创建索引,如 CREATE INDEX IAD ON AD(A, C) 和 EXPLAIN QUERY PLAN 显示该索引由 sqlite 引擎使用。

尽管如此,当我调用exportArchiveData服务器时,会正确发送数据,但在此期间无法执行其他操作。我有大量数据(要发送 5 - 1200 万行),因此大约需要 3 分钟。

如何防止它阻塞整个服务器?

我认为如果我使用 EACH 并且会有回调,服务器的响应速度会更快。而且内存使用量很大(大约 3GB 甚至更多)。我可以以某种方式阻止这种情况吗?

在回答评论时,我想补充一些说明:

我使用node-sqlite3 from developmentseed 。它应该是异步且非阻塞的。确实如此。准备好声明后,我可以请求主页。但是当服务器开始提供数据时,Node.js 服务器就会被阻塞。我想那是因为对主页的请求是一个调用回调的请求,而有数百万个处理存档数据“EACH”的回调请求。

如果我从 Linux 命令行使用 sqlite3 工具,我不会立即获取行,但这不是问题,只要 node-sqlite3 是非阻塞的。

是的。我正在达到 CPU 最大值。更糟糕的是,当我请求两倍的数据时,整个内存都会被使用,然后服务器永远卡住。

最佳答案

好的。我是这样处理这个问题的。

我没有使用 Database#each,而是使用 Database#prepare 和多个 Statement#get。

此外,我调查了内存不足是由响应缓冲区已满引起的。所以现在,当我获得上一行并且响应缓冲区有新数据的位置时,我会调用下一行。工作完美。现在服务器没有被阻止(仅在准备语句期间)。

Sqlite 模块:

module.exports.SS.prototype.fetchAllArchiveData = function (                  
a) {

var self = this;
var statement = self.Db.prepare(
'SELECT A, B, C '+
'FROM AD WHERE '+
' A="' + a + '"'+
' ORDER BY C ASC' +
';'
,
function(error){
if(error != null){
console.log(error);
}
}
);
return statement;
};

服务器端:

function exportArchiveData(response, query){                                    

var respRet = null;
var i = 0;
var statement = db.fetchAllArchiveData(
query.ID);
var getcallback = function(err, row){
if(err != null){
console.mylog(err);
return;
}
if(typeof(row) != 'undefined'){
respRet = response.write(row.A + ';' + row.B + ';' + row.C + '\n');
console.log(i++ + ' ' + respRet);
if(respRet){
statement.get(getcallback);
}else{
console.log('should wait on drain');
response.on('drain', function(){
console.log('drain - set on drain to null, call statement');
response.on('drain', function(){});
statement.get(getcallback);
});
}
}else{
response.end();
}
};

statement.get(function(err, row){
response.setHeader('Content-type', 'text/csv');
response.setHeader('Content-disposition', 'attachment; filename=archive.csv');
getcallback(err, row);
});
};

关于performance - 为什么要从 Node.JS 的 sqlite block 中获取数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17166584/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com