MySQL中的多个更新花费的时间太长

MySQL中的多个更新花费的时间太长,mysql,Mysql,每次循环代码时都会发生多个更新。在写这个问题的时候,我有80个单独的更新发生在同一个表中 这需要10.8秒。如果我不做更新(只把它们输出到屏幕上,这样我就能看到程序在做什么),需要2.7秒。8秒锁定数据库的时间过长:( 更新的一个例子是 UPDATE players SET energy=energy+14 WHERE playerID=243 LIMIT 1 UPDATE players SET energy=energy+7 WHERE playerID=258 LIMIT 1 UPDATE

每次循环代码时都会发生多个更新。在写这个问题的时候,我有80个单独的更新发生在同一个表中

这需要10.8秒。如果我不做更新(只把它们输出到屏幕上,这样我就能看到程序在做什么),需要2.7秒。8秒锁定数据库的时间过长:(

更新的一个例子是

UPDATE players SET energy=energy+14 WHERE playerID=243 LIMIT 1
UPDATE players SET energy=energy+7 WHERE playerID=258 LIMIT 1
UPDATE players SET energy=energy+3986 WHERE playerID=244 LIMIT 1
UPDATE players SET energy=energy+2990 WHERE playerID=245 LIMIT 1

有没有加快速度的方法?

一种方法是确保玩家的
能量
行上没有任何索引,并确保玩家ID
上有索引(索引减少查找时间,但增加更新/插入时间)

此外,我建议阅读一些想法。一个建议是尝试锁定表,更新所有内容,然后解锁。如果您能提供更多关于您正在运行的MySQL版本(以及您正在使用的数据库/表(MyIsam/InnoDB等)的信息,我可能会进一步帮助您


我希望这会有所帮助!

一个选项是确保玩家的
能量行上没有任何索引,并确保玩家ID上有索引(索引减少查找时间,但增加更新/插入时间)

此外,我建议阅读一些想法。一个建议是尝试锁定表,更新所有内容,然后解锁。如果您能提供更多关于您正在运行的MySQL版本(以及您正在使用的数据库/表(MyIsam/InnoDB等)的信息,我可能会进一步帮助您


我希望这会有帮助!

限制1条款的好处是什么?放弃它

您是否在
playerID
上有索引?如果没有,请添加一个索引

玩家表有多大?有多少行?每行有多大

您是否考虑过将操作参数化的准备好的UPDATE语句:

UPDATE Players SET Energy = Energy + ? WHERE PlayerID = ?
然后,您可以使用不同的参数多次执行此操作:

  14   243
   7   258
3986   244
2990   245

使用预先准备好的语句的优点是DBMS不必每次都重新分析SQL,因此它所做的工作更少。

限制1子句的好处是什么?放弃它

您是否在
playerID
上有索引?如果没有,请添加一个索引

玩家表有多大?有多少行?每行有多大

您是否考虑过将操作参数化的准备好的UPDATE语句:

UPDATE Players SET Energy = Energy + ? WHERE PlayerID = ?
然后,您可以使用不同的参数多次执行此操作:

  14   243
   7   258
3986   244
2990   245

使用prepared语句的优点是DBMS不必每次都重新分析SQL,因此它所做的工作更少。

索引和prepared听起来不错,但我不明白放弃
限制1
会有什么好处。最坏的情况下,它没有影响,最好的情况下,它会导致更早的返回。我们没有您的模式r表,但可能PlayerID是主键或对其具有唯一约束。如果是这样,则解析限制1(不是很多,但…)会涉及额外的工作,并且不会更改结果。如果不是唯一列,则限制1会导致数据库损坏(因为给定的PlayerID可能有不同的行,能量列的值也不同。此外,LIMIT子句不必要地限制了SQL的可移植性。我现在有以下代码$stmt=$mysqli->prepare(“更新玩家设置能量=:能量,信心=:信心,士气=:士气,其中PlayerID=:PlayerID”)$stmt->bindParam(':energy',$energy);$stmt->bindParam(':confidence',$confidence);$stmt->bindParam(':士气',$士气);$stmt->bindParam(':playerID',$playerID);$playerID=1;#关键是玩家ID$energy=1000;$confidence=1100;$士气=1200;$stmt->->execute();但这会产生一个致命错误:调用成员函数prepare()在非对象上,致命错误强烈表明$mysqli无效。此时,您正在钻研另一个领域,与上面的纯SQL问题有所不同。但是,我相当有信心,您需要确保连接正常工作并正确创建$mysqli。从逻辑上讲,您的操作顺序看起来是正确的。您使用的是Perl+DBI吗?索引和准备工作听起来不错,但我不明白放弃
限制1
会有什么好处。最坏的情况下,它没有影响,最好的情况下,它会导致更早的返回。我们没有表的架构,但可能PlayerID是主键或对它有唯一的约束。如果是这样,那么就有了解析限制1(不是很多,但是…)时需要额外的工作,并且不会改变结果。如果它不是唯一的列,则限制1会导致数据库损坏(因为给定的PlayerID可能有不同的行,能量列的值也不同。此外,LIMIT子句不必要地限制了SQL的可移植性。我现在有以下代码$stmt=$mysqli->prepare(“更新玩家设置能量=:能量,信心=:信心,士气=:士气,其中PlayerID=:PlayerID”)$stmt->bindParam(':energy',$energy);$stmt->bindParam(':confidence',$confidence);$stmt->bindParam(':士气',$士气);$stmt->bindParam(':playerID',$playerID);$playerID=1;#关键是玩家ID$energy=1000;$confidence=1100;$士气=1200;$stmt->->execute();但这会产生一个致命错误:调用成员函数prepare()在非对象上,致命错误强烈表明$mysqli无效。此时,您正在钻研另一个领域,与上面的纯SQL问题有所不同。但是,我相当有信心,您需要确保连接正常工作并正确创建$mysqli。从逻辑上讲,您的操作顺序看起来是正确的。你在使用Perl+DBI吗?你确定你的数据库中需要这个吗?也许你想要一个memcached层,在这两者之间