我正在尝试使用Knex.js将10M +行插入MySQL数据库。有没有一种方法可以使用for循环插入长度为10000的数组(这似乎是我能够插入的最大大小-大于此的任何大小都会得到“错误:ER_NET_PACKET_TOO_LARGE:得到了一个大于'max_allowed_packet'字节的数据包”)。
我尝试使用一个Promise链,但是该链很长,无法容纳1000万条记录。
exports.seed = (knex) => {
// Deletes ALL existing entries
return knex('books').del()
.then(() => {
const fakeBooks = [];
for (let i = 0; i < 10000; i += 1) {
fakeBooks.push(createFakeBooks());
}
return knex('books').insert(fakeBooks)
.then(() => {
const fakeBooks1 = [];
for (let i = 0; i < 10000; i += 1) {
fakeBooks1.push(createFakeBooks());
}
return knex('books').insert(fakeBooks1)
.then(() => {
const fakeBooks2 = [];
for (let i = 0; i < 10000; i += 1) {
fakeBooks2.push(createFakeBooks());
}
...
答案 0 :(得分:1)
如果您使用async
和await
并抛弃then
,则会更容易。然后可以这样写:
exports.seed = async (knex) => {
await knex('books').del();
let fakeBooks = [];
for (let i = 1; i <= 10000000; i += 1) {
fakeBooks.push(createFakeBooks());
if (i % 1000 === 0) {
await knex('books').insert(fakeBooks);
fakeBooks = [];
}
}
};
await
将使诺言在函数继续执行之前完成,而不会阻塞线程。该循环将运行一千万次,并每隔1000行插入一次数据库。您可以将其更改为10000行,但是最好使用1000行。
我自己只尝试了一百万行,因为插入一千万行花了太多时间。
答案 1 :(得分:0)
您可以使用https://knexjs.org/#Utility-BatchInsert来完成向数据库插入大量行的操作。
await knex.batchInsert('books', create10MFakeBooks(), 5000)
但是,您可能希望实际上以较小的批次来创建这些书,以防止使用GB的内存。因此,MikaS的答案是正确的,只需使用async / await,并且编写起来会很简单。
我不会使用knex进行此类工作,而是使用原始SQL。