【问题标题】:MySql INSERT vs PHP file_put_contentsMySql INSERT 与 PHP file_put_contents
【发布时间】:2012-03-10 12:10:16
【问题描述】:

我有一个快速增长、写入量大的 PHP/MySql 应用程序,它以每秒十几个左右的速度将新行插入到数百万行的 INNODB 表中。

我开始使用实时 INSERT 语句,然后转到 PHP 的 file_put_contents 将条目写入文件并使用 LOAD DATA INFILE 将数据导入数据库。哪种方法更好?

我应该考虑其他替代方案吗?我怎么能期望这两种方法在未来处理碰撞和增加的负载?

谢谢!

【问题讨论】:

  • 另一种方法是写入辅助表,然后在主表上进行批量“插入...选择”,如果对主表的写入成为问题。

标签: php mysql


【解决方案1】:

LOAD DATA INFILE 视为插入数据的批处理方法。它消除了为每个语句启动插入查询的开销,因此速度更快。但是,在处理错误时,您会失去一些控制。与文件中间的一行相比,处理单个插入查询的错误要容易得多。

【讨论】:

  • 您可以使用语法 insert into table values (row1),(row2),...,(rowN);使用单个查询插入尽可能多的行。您还可以附加“... on duplicate key update ...”来指定如何处理唯一键冲突
  • @atxdba 这对于大型插入来说是一个可怕的想法。
  • @feketegy 可怕吗?表现? tinyurl.com/7jmzbcp 是这样的帖子,说明它是如何更好和更受欢迎的。当然,您不想在单个插入中加载几场数据,而是做出一个笼统的未定义声明,这太可怕了,这是完全错误的。甚至 mysqldump 默认会创建批量插入。如果您说对于非常大的数据集加载数据可能会更好,我不会争辩。我真的只是在指出可用的语法。
  • @atxdba 由于性能问题,这太可怕了。它占用了大量的内存。当然,如果您使用几个值组,它不会影响性能,但是在大型插入时,将其插入数据库需要很长时间。对于非常大的数据,我会使用 prepared statementsload data infile
【解决方案2】:

根据您是否能够承受 PHP 插入的数据不能立即在表中可用,那么INSERT DELAYED 可能是一个选项。

MySQL 将接受要插入的数据并在稍后处理插入,将其放入队列中。所以这不会阻塞你的 PHP 应用程序,同时 MySQL 会确保稍后插入数据。

As it says in the manual:

使用 INSERT DELAYED 的另一个主要好处是来自多个客户端的插入被捆绑在一起并写入一个块中。这比执行许多单独的插入要快得多。

我已经使用它来记录数据丢失不是致命的数据,但是如果您想在尚未插入来自 INSERT DELAYED 的数据时防止服务器崩溃,您可以考虑将更改复制到专用从机。

【讨论】:

    【解决方案3】:

    我们处理插入的方式是将它们发送到像 ActiveMQ 这样的消息队列系统。从那里我们有一个单独的应用程序,它使用 LOAD DATA INFILE 分批加载大约 5000 个插入。错误处理仍然可以使用 infile 进行,但是它处理插入的速度要快得多。如果设置消息队列超出了您的应用程序的范围,那么 file_put_contents 没有理由不是一个可接受的选项——特别是如果它已经实现并且工作正常。

    此外,您可能希望在写入期间测试禁用索引,以查看这是否会提高性能。

    【讨论】:

    • 要考虑的另一点是您的特定系统的瓶颈在哪里。尝试使用 iostat 和 vmstat 来确定减速的位置以及应该集中精力的位置。根据您对数据的处理方式,有许多存储解决方案,如果不是 ACID 友好,其中一些解决方案会更快。
    【解决方案4】:

    听起来您不应该使用 innoDB。无论如何,即使对于糟糕的硬件,每秒十几次插入也不应该有问题 - 除非您的数据模型可能非常复杂,但为此, LOAD DATA INFILE 非常好,因为除其他外,它只重建索引一次,而不是在每个插入上。因此,使用文件是一种不错的方法,但请确保以仅附加模式打开它们。

    从长远来看(每秒 1k+ 次写入),请查看其他数据库 - 特别是用于编写繁重应用程序的 cassandra。

    【讨论】:

    • 索引也是我的想法。每次写入哪个会更快 - 附加到平面文件或插入到数据库?他们将如何处理并发请求?
    • 这真的取决于,您需要运行测试并为您的环境找出答案。仅当您将数据保持在限制范围内(我相信它在 linux 上是 4K)时,附加到文件才是原子的,否则您将遇到并发问题
    【解决方案5】:

    如果您确实使用了 sql 插入路由,请将 pdo 执行语句包装在事务中。这样做会大大加快进程。

    【讨论】:

      【解决方案6】:

      出于安全原因,LOAD DATA 在某些服务器上被禁用:

      http://dev.mysql.com/doc/mysql-security-excerpt/5.0/en/load-data-local.html

      另外,我不喜欢颠倒编写应用程序来维护数据库完整性。

      【讨论】:

        猜你喜欢
        • 2015-09-16
        • 2017-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-18
        • 2012-07-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多