简体   繁体   English

如何以缩放的方式执行多个MySQL INSERT(PHP)

[英]How to do multiple MySQL INSERTs in a way that scales (PHP)

We have a loop in our PHP code which inserts rows into a table. 我们在PHP代码中有一个循环,它将行插入表中。 eg: 例如:

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

This was fine a few months ago because the loop would only iterate several times. 几个月前这很好,因为循环只会迭代几次。 However, due to our website getting more traffic this loop now sometimes iterates 1000 or more times. 但是,由于我们的网站获得更多流量,此循环现在有时会迭代1000次或更多次。 The table has some overhead ( 4,305 KiB ) and SELECTs from this table are appearing in the MySQL slow-log , probably because they are having to wait for a long list of INSERTs to release the locks? 该表有一些开销4,305 KiB ),这个表中的SELECT出现在MySQL慢速日志中 ,可能是因为他们不得不等待一长串INSERT释放锁?

How should I optimise the code so it can scale better? 我应该如何优化代码以便更好地扩展?

Some things I thought I might try: 有些事情我认为我可能会尝试:

  • INSERT DELAYED - Need to look into it. INSERT DELAYED - 需要深入研究。 Could it help? 它有帮助吗?
  • Try inserting multiple rows in the same query. 尝试在同一查询中插入多行。 But what limit should I set? 但是我应该设置什么限制? 50, 500, 1000? 50,500,1000?

What is $someQuery ? 什么是$ someQuery Could you use INSERT ... SELECT syntax? 你能使用INSERT ... SELECT语法吗?

Instead of repeating mysql_query() , use prepared statements . 而不是重复mysql_query() ,使用mysql_query() 准备语句 They are a much more efficient way of repeating the same query many times with different values. 它们是使用不同值多次重复相同查询的更有效方式。

Also, I would look into those queries that are appearing in the slow log. 另外,我会查看那些出现在慢速日志中的查询。 Use EXPLAIN (<query>) to check that indexes are being used. 使用EXPLAIN (<query>)检查是否正在使用索引。

You can also build up a statement like this: 您还可以构建如下语句:

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

You can experiment with different limits to determine where, if anywhere, your SQL gets too long. 您可以尝试不同的限制来确定SQL的位置(如果有的话)太长。 Then you can set the limit to something sane. 然后你可以将限制设置为理智。

What Ben James said is important. 本詹姆斯所说的很重要。 Prepared statements are much faster if you execute the same SQL, and just change parameters in it. 如果执行相同的SQL,并且只更改其中的参数,则准备好的语句要快得多。

Also, You my try to change the whole loop to something like: 另外,我尝试将整个循环更改为:

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

Of course you have to adapt the $someQuery, so I selects only two columns which are of the same type (or can by cast automaticly) as the columns i and j. 当然你必须调整$ someQuery,所以我只选择两列相同类型的列(或者可以通过自动转换)作为列i和j。

If you do not have very complicated mechanism in php, then this shloud be possible and will be much faster than any php loop. 如果你在php中没有非常复杂的机制,那么这个shloud是可能的,并且将比任何php循环快得多。

One of the fastest ways to get data into MySQL is LOAD DATA INFILE . 将数据导入MySQL的最快方法之一是LOAD DATA INFILE Think of it as a CSV import. 可以将其视为CSV导入。 You could write your data one row at a time to disk and then do a bulk load. 您可以将数据一次一行写入磁盘,然后进行批量加载。 According to this page on insert speeds LOAD DATA INFILE is 20x faster than a straight INSERT . 根据这个关于插入速度的页面, LOAD DATA INFILE比直接INSERT快20倍。

There may be other undesirable side-effects, though, as the table may well be locked for the whole process rather than just one row at a time. 但是,可能存在其他不期望的副作用,因为表可能在整个过程中被锁定而不是一次只锁定一行。 Running this in eg 100 row batches may make both parts of the problem manageable - I think you'll just need to experiment. 在例如100行批次中运行这可以使问题的两个部分都易于管理 - 我认为你只需要进行实验。

There are stored procedures and function in new versions of MySQL. 新版本的MySQL中存在过程和函数。 You can use there a structured language with variables, loops and conditional blocks. 您可以在那里使用带有变量,循环和条件块的结构化语言。 One stored procedure should be faster than many independent inserts. 一个存储过程应该比许多独立插入更快。 However, it is a new language to learn. 但是,这是一门新学习的语言。

You need mysqli extension in php, to use stored procedures. 你需要php中的mysqli扩展,才能使用存储过程。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM