我试图使用sqlite3将整个knex.js数据库表导出到CSV。由于表最多可以有300000行,所以我使用流来避免内存问题。但是,如果我查看我的应用程序的内存使用情况,它高达800 my,或者我有一个“内存不足”错误。
如何使用knex.js处理sqlite3数据库上的大型查询结果?
下面是代码示例:
knex.select().from(table).stream(function (stream) {
var stringifier = stringify(opts);
var fileStream = fs.createWriteStream(file);
var i = 0;
stringifier.on('readable', function() {
var row;
while (row = stringifier.read()) {
fileStream.write(row);
console.log("row " + i++); //debug
}
});
fileStream.once('open', function(fd) {
stream.pipe(stringifier);
});
});编辑
似乎用于knex.js数据库的sqlite3流是“假的”流。sqlite3的流函数的源代码如下:
Runner_SQLite3.prototype._stream = Promise.method(function(sql, stream, options) {
/*jshint unused: false*/
var runner = this;
return new Promise(function(resolver, rejecter) {
stream.on('error', rejecter);
stream.on('end', resolver);
return runner.query(sql).map(function(row) {
stream.write(row);
}).catch(function(err) {
stream.emit('error', err);
}).then(function() {
stream.end();
});
});
});我们看到它在从结果数组创建流之前等待执行请求。
版本:
谢谢你的帮助。
发布于 2015-03-31 08:38:00
我认为没有解决办法。我使用限制和偏移一步一步地用knex.js获取所有数据,并将每一行写入一个写流中。对于那些想要实现的人来说,一个实现示例:
exportTable: function(table, writeStream) {
var totalRows;
var rowLimit = _config.ROW_LIMIT;
return DatabaseManager.countAll(table).then(function(count) {
totalRows = count[0]['count(*)'];
var iterations = new Array(Math.ceil(totalRows / rowLimit));
return Promise.reduce(iterations, function(total, item, index) {
return _knex.select().from(table).limit(rowLimit).offset(index * rowLimit).map(function(row) {
writeStream.write(row);
}).catch(function(err) {
return Promise.reject(err);
});
}, 0).then(function() {
return Promise.resolve();
}).catch(function(err) {
return Promise.reject(err);
});
}).catch(function(err) {
console.log(err);
return Promise.reject(err);
});
}https://stackoverflow.com/questions/29236310
复制相似问题