MySql插入 vs PHP file_put_contents

5

我有一个快速增长的、写入负载较重的PHP/MySql应用程序,每秒向包含数百万行的INNODB表中插入十几个新行。

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

还有其他可供考虑的选择吗?我该如何预计这两种方法在未来处理冲突和增加负载的情况下的表现?

谢谢!


一个替代方案是先写入到一个辅助表中,然后通过批量的“insert into... select from”操作将数据插入到主表中,如果对主表的写入已经成为一个问题的话。 - Marc B
6个回答

3

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


你可以使用语法 insert into table values (row1),(row2),...,(rowN); 来一次性插入多行数据。你还可以添加 "... on duplicate key update ..." 来指定如何处理唯一键冲突。 - atxdba
@atxdba 在大批量插入时,那是一个可怕的想法。 - feketegy
@feketegy 什么方面很糟糕?性能?http://tinyurl.com/7jmzbcp 这篇 Stack Overflow 的帖子解释了为什么使用这种方法更好、更受欢迎。当然,你不想在单个插入中加载数千兆字节的数据,但是对于一个笼统的未定义的说法,即它很糟糕,这是完全错误的。即使 mysqldump 默认也会创建批量插入。如果你说对于非常大的数据集,load data 可能更好,我不会反驳。我只是指出了可用的语法。 - atxdba
@atxdba 这很糟糕,因为存在性能问题。它占用了大量的内存。如果您只使用几个值组,那么它不会影响性能,但是在大型插入操作中,将其插入数据库需要很长时间。我建议对于真正大量的数据,可以使用“预处理语句”或“load data infile”。 - feketegy

2
根据您是否能够承受PHP插入的数据不会立即在表中可用,那么INSERT DELAYED可能是一个选项。
MySQL将接受要插入的数据,并稍后处理插入,将其放入队列中。因此,在MySQL确保稍后插入数据时,这不会阻止您的PHP应用程序。
正如手册中所说,另一个主要好处是使用INSERT DELAYED是许多客户端的插入被捆绑在一起并写入一个块。这比执行许多单独的插入要快得多。 我已经将其用于记录数据,在这种情况下,数据丢失不是致命的,但如果您想保护服务器崩溃时尚未插入来自INSERT DELAYED的数据,则可以查看将更改复制到专用从属机器。

0
我们处理插入的方式是将它们发送到像ActiveMQ这样的消息队列系统。从那里,我们有一个单独的应用程序,使用LOAD DATA INFILE批量加载插入,每次大约5000个。错误处理仍然可以在infile中进行,但它处理插入的速度更快。如果设置消息队列超出了您的应用程序范围,那么file_put_contents也是一个可接受的选项--特别是如果它已经实现并且正常工作。
此外,您可能希望测试在写入时禁用索引以查看是否提高了性能。

另一个需要考虑的点是你特定系统的瓶颈在哪里。尝试使用 iostat 和 vmstat 确定你的减速出现在哪里以及你应该集中精力解决的地方。根据你正在处理数据的方式,有许多存储解决方案,其中一些比 ACID 友好的解决方案快得多。 - RumpRanger

0

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

从长远来看(每秒1k+的写入),请查看其他数据库——特别是针对写入密集型应用程序的cassandra。


索引也在我的考虑范围内。每次写入哪种方式更快——追加到平面文件还是插入到数据库?它们如何处理并发请求? - user1259956
这真的取决于情况,你需要运行测试并为你的环境找出解决方案。如果你在限制范围内保留数据(我相信在Linux上是4K),那么向文件追加只是原子性的,否则你将会遇到并发问题。 - miki

0
如果您选择使用sql插入方法,请将pdo执行语句包装在事务中。这样做将极大地加快过程。

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接