MySQL - 如何快速插入数百万行?

时间:2014-07-19 03:46:59

标签: mysql sql

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

开发人员通常做了多少行来测试他们的程序可以处理它们的速度?

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

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

5 个答案:

答案 0 :(得分:2)

  1. 编写脚本以生成数据
  2. 使用输出插入数据库
  3. 一夜之间
  4. 在做它的东西时享受那品脱

答案 1 :(得分:2)

从您的问题中不清楚您需要插入的数据的性质是什么,但如果可以在最快的方式生成,则可以在一个查询中执行(将插入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

这是针对10k行的 SQLFiddle 演示

推荐阅读:

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

我猜您插入的记录如下:

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 :(得分:1)

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

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

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

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

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

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


第二个选项:不要使用INSERT,请使用LOAD DATA INFILE。即使使用预准备语句和多行语法,这也比使用INSERT快一个数量级。

第三个选项:将批量数据准备为CSV文件,将其移动到MySQL的数据目录中,然后创建一个指向该文件的ENGINE=CSV表。瞧,你有一张满是数据的桌子。然后使用ALTER TABLE ENGINE=InnoDB并将其转换为真实的内部表格。