2

我们的 PHP 代码中有一个循环,它将行插入到表中。例如:

while ($info = mysql_fetch_assoc($someQuery)) {
    mysql_query("INSERT INTO X (i,j) VALUES ($info['ii'],$info['jj'])");
}

几个月前这很好,因为循环只会迭代几次。然而,由于我们的网站获得更多流量,这个循环现在有时会重复 1000 次或更多次。该表有一些开销4,305 KiB),并且该表中的 SELECT 出现在MySQL 慢日志中,可能是因为它们必须等待一长串 INSERT 才能释放锁?

我应该如何优化代码以便它可以更好地扩展?

我认为我可以尝试的一些事情:

  • 插入延迟- 需要调查一下。能帮上忙吗?
  • 尝试在同一个查询中插入多行。但是我应该设置什么限制?50、500、1000?
4

6 回答 6

7

什么是$someQuery?你可以使用INSERT ... SELECT语法吗?

于 2010-01-28T10:33:11.407 回答
4

不要重复mysql_query(),而是使用准备好的语句。它们是使用不同值多次重复相同查询的更有效方式。

另外,我会查看慢日志中出现的那些查询。用于EXPLAIN (<query>)检查是否正在使用索引。

于 2010-01-28T10:31:16.360 回答
4

您还可以建立这样的语句:

INSERT INTO X (i,j)
VALUES ($info['ii'],$info['jj']),
(val, val),
...
(val, val);

您可以尝试不同的限制来确定您的 SQL 在哪里(如果在任何地方)变得太长。然后,您可以将限制设置为理智的东西。

于 2010-01-28T11:00:35.540 回答
2

本詹姆斯所说的很重要。如果您执行相同的 SQL,并且只需更改其中的参数,则准备好的语句会快得多。

另外,您尝试将整个循环更改为:

INSERT INTO x (i, j) SELECT (here goes your $someQuery)

当然,您必须调整 $someQuery,因此我只选择与 i 和 j 具有相同类型(或可以自动转换)的两列。

如果您在 php 中没有非常复杂的机制,那么这应该是可能的,并且比任何 php 循环都要快得多。

于 2010-01-28T10:38:48.417 回答
2

将数据导入 MySQL 的最快方法之一是LOAD DATA INFILE. 将其视为 CSV 导入。您可以一次将数据一行写入磁盘,然后进行批量加载。根据this page on insert速度 LOAD DATA INFILE比直线快20倍INSERT

但是,可能还有其他不良副作用,因为该表很可能在整个过程中被锁定,而不是一次只锁定一行。在例如 100 行批次中运行它可能会使问题的两个部分都易于管理 - 我认为您只需要进行试验。

于 2010-01-28T11:18:09.140 回答
1

新版本的 MySQL 中有存储过程和函数。您可以在那里使用带有变量、循环和条件块的结构化语言。一个存储过程应该比许多独立的插入更快。但是,它是一种新的语言,需要学习。

您需要 php 中的 mysqli 扩展,才能使用存储过程。

您还可以查看 mysqli_multi_query。
http://pl.php.net/manual/en/mysqli.multi-query.php

于 2010-01-28T21:36:31.410 回答