在 pdo 准备好的语句中执行多插入或许多不同的插入更好/更快吗?

Posted

技术标签:

【中文标题】在 pdo 准备好的语句中执行多插入或许多不同的插入更好/更快吗?【英文标题】:Is it better/faster to do a multi insert or a many different insert in a pdo prepared statement? 【发布时间】:2016-01-05 17:10:22 【问题描述】:

我需要使用 pdo 准备语句从 php 一次将 1000-30000 行(每个由 19 个元素组成)插入到 mysql 表中。我在问自己是做许多不同的插入还是一个大的多插入更好,比如:

INSERT INTO table (a,b,c,...) VALUES (value0a, value0b, value0c,...), (value1a, value1b, value1c,...), ..., (value10000a, value10000b, value10000c,...)

VS exec 在事务中的每个插入

INSERT INTO table (a,b,c,...) VALUES (value0a, value0b, value0c,...);
INSERT INTO table (a,b,c,...) VALUES (value1a, value1b, value1c,...);
INSERT INTO table (a,b,c,...) VALUES (value2a, value2b, value2c,...);
...
INSERT INTO table (a,b,c,...) VALUES (value10000a, value10000b, value10000c,...);

看起来多插入更好,所以我必须知道我需要插入多少行并为它们创建一个 (?,?,?,...) 占位符,然后将它们绑定在一个循环中? 考虑到 PDOStatement::debugDumpParams() 没有显示参数值,我如何在插入时回显整个查询?

【问题讨论】:

根据 mysql 站点上的文档,使用第一种插入语句的方法更快 我实际上在几周前就这个主题做了一些非正式的基准测试。像往常一样,它并不像第一次出现那样清晰。虽然,一旦你有了multi insert 语句,它比在带有绑定的每个循环中的单个准备插入要快约 30-40%。我的电脑上的时间分别约为 2 秒和 3 秒。问题是在 PHP 中生成 multi insert 语句的成本。这花了大约8秒。如果您可以有效地生成多插入语句,那么它会更快。如果您经常这样做,那么额外的复杂性是值得的。 如果这个“线程”可以与***.com/questions/1793169/…合并就好了。这个包含准备好的语句,而另一个不包含。 【参考方案1】:

当你准备一个语句时,它会被分析一次并且执行计划已经准备好。剩下的就是填写数据了。由于几个原因,这要好得多

词法分析完成一次​​ 执行计划已准备就绪 max_packet_size 不会有问题,因为如果您发送批量插入并且查询很大,MySQL 可以拒绝它 在循环中使用这样的语句,提供数据并执行更容易

速度问题与您的硬盘有关。基本上,如果您开始一个事务,发出 100 个(或 200 个)插入然后commmit 事务 - 您将看到速度的巨大提高。这就是我们通过花费 1 个 I/O 并使用大量磁盘带宽来实现快速插入速率的方法。

【讨论】:

这是代码复杂性和性能之间的一个很好的折衷。我首先使用这种方法——它通常足够快。即使在 PC 上,它也会每秒插入数百条记录。【参考方案2】:

您多久这样做一次? 如果您经常这样做(一天一次,一周多次),请尝试混合使用“many-inserts-per-line”和“many-line-inserts”,这样您就有 5 到 10 个连续插入。

【讨论】:

【参考方案3】:

更快的方式二在表中插入数据

   INSERT INTO your_tbl
        (a,b,c)
    VALUES
        (value0a,value0b,value0c),
        (value1a,value1a,value1a)

【讨论】:

【参考方案4】:

就在这里:Which is faster: multiple single INSERTs or one multiple-row INSERT?

http://dev.mysql.com/doc/refman/5.0/en/insert-speed.html

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

    Connecting: (3)
    Sending query to server: (2)
    Parsing query: (2)
    Inserting row: (1 × size of row)
    Inserting indexes: (1 × number of indexes)
    Closing: (1)

从这里应该很明显,发送一个大的声明将 每个插入语句为您节省 7 的开销,这进一步 读文还说:

如果您同时从同一个客户端插入多行, 使用带有多个 VALUES 列表的 INSERT 语句来插入多个 一次行。这要快得多(在某些情况下要快很多倍 例)而不是使用单独的单行 INSERT 语句。

【讨论】:

您如何得出“每个插入语句的开销为 7”?以及如何使用准备好的语句? 那部分是从我认为的上一个答案中复制而来的 首先这个是对的,这个是抄的,不过我在第一行也是这么说的。我知道这个主题,这是作为实例的第一个答案 在大多数情况下,当您可以复制粘贴另一个问题的答案时,意味着新问题是重复的 -> 将其标记为重复而不是复制答案。 错误结论。自然,解析一次查询会更快——这正是准备好的语句的用途——MySQL 解析一次,然后你只需提供数据。这样可以避免很多问题,如果你想快速插入,可以用事务块包装插入。【参考方案5】:

SQL 查询越少越好。所以做单个大插入更好,因为它会减少数据库交互并节省大量处理时间。

【讨论】:

以上是关于在 pdo 准备好的语句中执行多插入或许多不同的插入更好/更快吗?的主要内容,如果未能解决你的问题,请参考以下文章

单例连接 + 单例准备好的语句

限制准备好的语句一次执行一个查询

准备好的语句中的占位符

在准备好的语句中不向列 X 插入值的逻辑 [重复]

Kohana 准备好的语句或查询构建?

PDO 准备好的语句有多安全?