【问题标题】:MySQL - How to rapidly insert million of rows? [duplicate]MySQL - 如何快速插入数百万行? [复制]
【发布时间】:2014-07-19 03:46:59
【问题描述】:

因此,出于开发目的,我需要一个包含大约 100 万到 1 亿个值的表,我目前的方法一点也不快。

开发人员通常会做什么来让他们的表包含数百万行来测试他们的程序处理它们的速度有多快?

我当前的方法有 10 个 for 循环,但对于我需要的行数来说它真的很慢。

那么我该怎么做才能快速插入数百万行?,在这种情况下,专业开发人员会做什么?

【问题讨论】:

标签: mysql sql


【解决方案1】:

从您的问题中不清楚您需要插入的数据的性质是什么,但如果它可以动态生成,那么最快的方法是在一个查询中进行(这将插入 1m 的客户),例如这个

INSERT INTO customers (id, customer_name)
SELECT n, CONCAT('Customer', n)
  FROM
(
select a.N + b.N * 10 + c.N * 100 + d.N * 1000 + e.N * 10000 + f.N * 100000 + 1 N
from (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) a
      , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) b
      , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) c
      , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) d
      , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) e
      , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) f
) t

这里是 SQLFiddle 10k 行的演示

推荐阅读:

【讨论】:

    【解决方案2】:

    通常,插入中最慢的部分是更新索引。要加快批量插入,请禁用索引,发送插入,然后重新启用它们。

    另外,使用多插入语法之一,而不是为每一行发出INSERT 语句。

    【讨论】:

    • 如何禁用索引?,我假设它的 ALTER TABLE tbl_name DISABLE KEYS?
    • 不要禁用索引,使用 LOAD DATA 命令
    【解决方案3】:

    我猜你像下面这样插入你的记录:

    INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
    INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
    INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
    INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
    INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2");
    

    改用这个:

    INSERT INTO `table1` (`field1`, `field2`) VALUES ("data1", "data2"),
                                                     ("data1", "data2"),
                                                     ("data1", "data2"),
                                                     ("data1", "data2"),
                                                     ("data1", "data2");
    

    注意:要优化插入速度,请将许多小操作组合成一个大操作。理想情况下,您建立一个连接,一次发送许多新行的数据,并将所有索引更新和一致性检查延迟到最后。

    【讨论】:

      【解决方案4】:

      最快的解决方案是根本不加载数据,而是从预先填充的数据目录开始。

      如果您只是为开发/测试初始化​​数据,则根本不要加载数据。从物理备份启动一个新的 MySQL 实例。

      您可以使用 Percona XtraBackup 对任何正在运行的 MySQL 实例进行物理备份,而不会阻塞流量。

      然后准备备份,它可以立即用作实时数据目录。

      然后您可以尽快设置一个新的测试实例,运行cp 来复制该数据目录,并启动一个 mysqld 实例,指定 --datadir 到您的备份副本。

      您可以重复此操作,将物理备份复制到所需数量的开发/测试实例。


      第二个选项:不要使用INSERT,使用LOAD DATA INFILE。这可能比使用 INSERT 快​​一个数量级,即使使用准备好的语句和多行语法也是如此。

      第三种选择:将批量数据准备为 CSV 文件,将其移动到 MySQL 的数据目录中,然后创建一个表,其中 ENGINE=CSV 指向该文件。瞧,你有一个充满数据的表。然后使用ALTER TABLE ENGINE=InnoDB,将其转换为真正的内表。

      【讨论】:

        【解决方案5】:
        1. 编写脚本生成数据
        2. 使用输出插入数据库
        3. 只跑一夜
        4. 尽情享受那一品脱的乐趣

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-10
          • 1970-01-01
          • 2022-11-12
          • 1970-01-01
          • 1970-01-01
          • 2023-03-21
          相关资源
          最近更新 更多