【问题标题】:MySQL Insert Query OptimizationMySQL 插入查询优化
【发布时间】:2016-09-24 10:22:52
【问题描述】:

以下两种方法中哪一种在向表中插入大量行时会更快。

查询方法一:逐一执行查询。

INSERT INTO tbl_user(id, name, number) VALUES(NULL, 'A', '9999999999');
INSERT INTO tbl_user(id, name, number) VALUES(NULL, 'B', '9999999999');
INSERT INTO tbl_user(id, name, number) VALUES(NULL, 'C', '9999999999');

查询方式二:一次查询。

INSERT INTO tbl_user(id, name, number) VALUES(NULL, 'A', '9999999999'),
                                             (NULL, 'B', '9999999999'), 
                                             (NULL, 'C', '9999999999');

【问题讨论】:

  • 方法2,因为它只执行一次。
  • 方法2比第一种快
  • 我们在这里展示了有多少人不知道发生了什么。您想要一一执行。你永远不想做第二个选项。为什么?因为如果您将第一个方法包装在事务块中并使用准备好的语句 - 您将永远不会因为max_packet_size 而遇到错误。选项 2 也需要更多的资源来解析。你总是想避免这种情况,如果发生任何不好的事情,调试也会变得更加困难。因此 - 选项#3 是最快的。在开头添加BEGIN TRANSACTION,在末尾添加COMMIT。祝你好运。

标签: php mysql database performance


【解决方案1】:

由于有一些争论,我想我会尝试一个基准测试,但首先

 CREATE TABLE `tbl_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `number` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB 

然后,我使用 2 行 python 生成问题中形式的 SQL 查询。

场景 1:
许多单个插入,每个查询都完全相同

INSERT INTO tbl_user VALUES(NULL,'A','9999999');
INSERT INTO tbl_user VALUES(NULL,'A','9999999');

1000 行;三个执行的平均(平均)运行时间 45.80 秒
5000 行;单次跑220秒

场景 2:
单个查询插入 1000 行,如下所示:

INSERT INTO tbl_user VALUES(NULL,'A','9999999'),
(NULL,'A','9999999'),
(NULL,'A','9999999'),
(NULL,'A','9999999'),

1000 行 3 次执行的平均(平均)运行时间 0.17 秒
5000 行 3 次执行的平均(平均)运行时间 0.48
10000 行 3 次执行的平均(平均)运行时间 1.06

场景 3:
与场景 1 类似,但在插入语句周围添加了 START TRANSACTIONCOMMIT

1000 行 3 次执行的平均(平均)运行时间 0.16 秒
5000 行 3 次执行的平均(平均)运行时间 0.48
10000 行 3 次执行的平均(平均)运行时间 0.91

结论:
方案 2,这是在其他两个答案中提出的,确实在很大程度上优于方案 1。有了这些数据,很难在 2 和 3 之间做出选择。需要对更多数量的刀片进行更严格的测试。但是如果没有这些信息,我可能会选择三个,原因是解析一个非常大的字符串通常有开销,准备一个也有!我怀疑如果我们尝试在单个语句中一次插入大约 50,000 条记录,它实际上可能会慢很多。

【讨论】:

  • 用恰当的例子完美回答。
  • 很高兴能帮上忙
【解决方案2】:

第二种方法(查询)比第一种更快。

因为在第一种方法中它在一个表上执行三个不同的查询,而在第二种方法中它只执行一次以在表中插入多条记录。

当您一次插入数百行时,您会发现主要区别。

【讨论】:

    【解决方案3】:

    第二次查询比第一次快得多。根据document,有助于提高单个语句中多次插入性能的因素是:-

    9.2.2.1 INSERT 语句的速度

    为了优化插入速度,将许多小操作合并到一个 大手术。理想情况下,您建立一个连接,发送数据 一次处理许多新行,并延迟所有索引更新和一致性 检查到最后。

    插入一行所需的时间由以下决定 因素,其中数字表示近似比例:

    连接:(3)

    向服务器发送查询:(2)

    解析查询:(2)

    插入行:(1 × 行大小)

    插入索引:(1 × 索引数)

    结束:(1)

    如果您要同时从同一个客户端插入多行,请使用带有多个 VALUES 列表的 INSERT 语句一次插入多行。这比使用单独的单行 INSERT 语句要快得多(在某些情况下快很多倍)。如果要向非空表添加数据,则可以调整 bulk_insert_buffer_size 变量以使数据插入更快。

    【讨论】:

    • 方法 #2 一点也不快。你只提供了一半的信息。如果有的话,它会更慢。您引用的文档有一个有趣的点 - To optimize insert speed, combine many small operations into a single large operation - 我们通过使用事务来做到这一点,而不是通过发送大量文本供 MySQL 解析。我不会对你的答案投票,但这完全是误导。
    • 这对于优化来说是很普遍的事情。阅读我在答案中添加的下段,而不是引用。这再次来自我添加的同一个文档“如果您同时从同一个客户端插入许多行,请使用带有多个 VALUES 列表的 INSERT 语句一次插入几行。这要快得多(在在某些情况下)而不是使用单独的单行 INSERT 语句“
    • 所以你认为发送一个 MySQL 必须解析的 512mb 字符串比发送你想要插入的值更快,包裹在事务中?您知道事务对 HDD I/O 的作用吗?
    猜你喜欢
    • 2020-08-18
    • 2012-10-06
    • 2023-03-03
    • 2022-10-24
    • 1970-01-01
    • 2014-03-21
    • 2011-01-22
    • 2011-07-07
    • 2018-12-21
    相关资源
    最近更新 更多