代码之家  ›  专栏  ›  技术社区  ›  Tom

如何以可伸缩的方式执行多个MySQL插入(PHP)

  •  2
  • Tom  · 技术社区  · 15 年前

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

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

    几个月前还可以,因为循环只会重复几次。然而,由于我们的网站获得了更多的流量,这个循环现在有时迭代1000次或更多次。桌子上有一些 overhead ( 4305 KIB )并从该表中选择出现在 MySQL slow-log ,可能是因为它们必须等待一长串插入才能释放锁?

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

    我想我可以尝试的一些事情:

    • INSERT DELAYED -需要调查一下。能帮上忙吗?
    • 尝试在同一查询中插入多行。但是我应该设置什么限制呢?50, 500, 1000?
    6 回复  |  直到 13 年前
        1
  •  7
  •   Alex Barrett    15 年前

    是什么 $查询 ?你能用吗? INSERT ... SELECT 语法?

        2
  •  4
  •   Ben James    15 年前

    而不是重复 mysql_query() 使用 prepared statements . 它们是使用不同值多次重复相同查询的更有效的方法。

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

        3
  •  4
  •   Phil Wallach    15 年前

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

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

    您可以使用不同的限制进行试验,以确定SQL在哪里(如果有的话)变得太长。然后你可以把限制设定为理智的东西。

        4
  •  2
  •   SWilk    15 年前

    本·詹姆斯的话很重要。如果您执行相同的SQL,并且只更改其中的参数,那么准备好的语句就快得多。

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

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

    当然,您必须调整$somequery,所以我只选择两个与i和j列类型相同(或者可以通过自动强制转换)的列。

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

        5
  •  2
  •   Karl B    15 年前

    将数据导入MySQL的最快方法之一是 LOAD DATA INFILE .把它当作一个csv导入。您可以将数据一次写入磁盘一行,然后进行批量加载。根据 this page on insert speeds 加载数据填充 比直线快20倍 INSERT .

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

        6
  •  1
  •   Michas    15 年前

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

    您需要使用PHP中的mysqli扩展来使用存储过程。

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