我想将文件插入包含对象数组(行)的数据库中。我在25个文件夹中有近8000个文件,近40000条记录。
我收到 TimeoutError:ResourceRequest超时。
我尝试增加续集的连接时间,但在前一千行后给出错误。我怎样才能正确,有效地向本地数据库插入40000行数据?
let folders_path = path.join(__dirname, "extracted_subjects/*");
function bulk_insert() {
glob(folders_path, readFolders);
}
function readFolders(err, folders) {
if (err) {
console.log("ERROR readFolders: ", err);
return;
}
folders.forEach(function(file) {
glob(path.join(file, "/*.json"), readFiles);
});
}
function readFiles(err, files) {
if (err) {
console.log("ERROR readFiles: ", err);
return;
}
files.forEach(async function(fileName) {
//console.log(fileName);
let promise = getData(fileName, "utf8")
.then(data => {
try {
// Parse And Bulk Create
let obj = JSON.parse(data);
models.dream
.bulkCreate(obj)
.then(function() {
console.log("File: inserted!");
})
.catch(err => console.log("Error", err));
} catch (SyntaxError) {
console.log("File: ", fileName);
return;
}
})
.catch(err => console.log(err));
await promise;
});
}
function getData(fileName, type) {
return new Promise(function(resolve, reject) {
fs.readFile(fileName, type, (err, data) => {
err ? reject(err) : resolve(data);
});
});
}
答案 0 :(得分:0)
您可以增加连接的默认设置,例如(您可以阅读文档中的默认设置):
dialectOptions: {
timeout: 30
},
operatorsAliases: Sequelize.Op,
pool: {
max: 5,
min: 0,
idle: 30000,
maxConnections: 5,
maxIdleTime: 30
},
但是我怀疑您最大的问题是,您正在尝试读取所有文件并继续打开与数据库的新连接,而您没有时间将它们全部写入,并且它们自然会超时
我怀疑这种行为不是您想要写的
files.forEach(async function (fileName) {
let promise = getData(fileName, 'utf8');
// ...
await promise;
});
这部分代码使用的是async和await一词,这不是使它们顺序读取,它们仍然能够并行运行。您将尽快调用getData
函数,然后开始轰炸models.dream.bulkCreate
。 bulkCreate
的使用在这里没有意义,因为您不是要批量创建任何内容,而是要逐个创建
选项是:
a)保持类似的代码,但是每块写一次,以25到25的速度并行处理文件,此更改会更大一些,在内存中读取25,在数据库中批量写入,再读取下25,依此类推... < br />
b)保持相似的代码,但是将文件25乘25并行读取,每块25写入,此更改会更大一些,打开并读取25个文件,然后每写入一个文件仅一行,然后继续
c)保留相似的代码,但不要读取每个文件并将其写入数据库,而是将它们保存在内存中,并在拥有所有数据后最后一次将所有数据写入一次。但是,在这种大数据的情况下,您可能会用完内存
d)如果性能不是问题,因为您想要(或需要)(一次)执行一次,您可以简单地循环浏览所有文件并以同步模式读取它们,因此它总是一个接一个地运行。 >
files.forEach(async function (fileName) {
let data = fs.readFileSync(fileName, 'utf8'); // read the file sync
try {
let parsedData = JSON.parse(data); // try parsing
models.dream // and inserting
.create(parsedData) // this should not be bulkCreate, right??
// this is kinda wrong, it doesn't automatically mean it
// is inserted, but it is copy paste from above
.then(res => console.log('File: inserted!'))
.catch(err => console.log('Error', err));
} catch (SyntaxError) {console.log('File: ', fileName);}
};
这段代码正在做的是确保您实际上按顺序逐个文件运行,这将大大降低您的执行速度,但是由于您最初表示要在本地主机上执行此操作,所以我认为您有时间让它继续运行。您仍然冒着读取文件的速度快于数据库处理文件的速度的风险,但是这次与下一个文件的同步读取相差无几,并且系统应该能够保持同步,特别是如果您增加允许的数量连接池中。
在生产方面,我可能会选择选项a或b,这取决于我是否提前知道最大文件大小/文件数。