如何使用Knex.js在MySQL数据库中插入1000万行?

时间:2019-05-20 17:09:17

标签: javascript mysql node.js knex.js

我正在尝试使用Knex.js将10M +行插入MySQL数据库。有没有一种方法可以使用for循环插入长度为10000的数组(这似乎是我能够插入的最大大小-大于此的任何大小都会得到“错误:ER_NET_PACKET_TOO_LARGE:得到了一个大于'max_allowed_pa​​cket'字节的数据包”)。

我尝试使用一个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());
              }
...

2 个答案:

答案 0 :(得分:1)

如果您使用asyncawait并抛弃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。