在巨大的 table 上加速简单的 UPDATE 查询

Speeding up a simple UPDATE query on a huge table

这是我的 table:

+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| CLID     | int(11)      | NO   | MUL | NULL    |       |
| calldate | datetime     | YES  | MUL | NULL    |       |
| src      | varchar(20)  | YES  |     | NULL    |       |
| dst      | varchar(20)  | YES  |     | NULL    |       |
| billsec  | varchar(10)  | YES  |     | NULL    |       |
| duration | time         | YES  |     | NULL    |       |
| debt     | float        | YES  | MUL | NULL    |       |
| region   | varchar(255) | YES  |     | NULL    |       |
| uniqueid | varchar(20)  | NO   | PRI | NULL    |       |
+----------+--------------+------+-----+---------+-------+

它有超过 490,328 条记录。我必须更新此 table 中的每条记录。这是查询(我在 PHP 中使用 mysqli):

UPDATE `All` 
SET `debt` = '$debt', `region` = '$region' 
WHERE `uniqueid` = $uid;

不幸的是,执行单个查询大约需要 1.4519529342651 秒。有什么办法可以加快速度吗?

1.45 秒更新单条记录是非常糟糕的性能,而且非常出乎意料。您的查询打算使用主键更新单行。你不应该注意到时间的长短。

但是,由于条件的表达方式,引擎无法将主键索引用于此查询。让我们更详细地查看查询:

UPDATE `All` 
SET `debt` = '$debt', `region` = '$region' 
WHERE `uniqueid` = $uid;
-------------------^

除非 $uid 在值中包含 引号 ,否则它将被视为字符串以外的其他内容。因此,如果您传入“1”,则与字符串相比,您得到的是一个整数。这可以防止索引的使用。哎呀

我的第一个建议是使用参数修复您的查询。除此之外,将单引号放在:

UPDATE `All` 
SET `debt` = '$debt', `region` = '$region' 
WHERE `uniqueid` = ''$uid'';

如果 uniqueid 实际上看起来像一个数字,请考虑将其存储为数字而不是字符串。

当然也有可能是其他地方出错了,比如:

  • 其他查询可能正在锁定 table。
  • 您可以从冷启动开始测试查询,所有后续查询都将非常快。
  • table 的触发器可能非常慢。

编辑:在执行我建议的操作之前,我肯定会尝试 Gordon Linoff 的解决方案,因为它很有意义(缺少围绕 where 子句传递的值的引号)。

您的 MySQL 数据库距离您的 PHP 服务器远吗?这可以解释糟糕的表现。

如果直接在 phpMyAdmin 界面上执行此操作时性能更好,我会尝试同时传递多个更新(参见 http://php.net/manual/en/mysqli.quickstart.multiple-statement.php)。

就像那样(这不是实际代码,只是为了让您了解我的意思):

$i = 0;
$query = '';

while (yourcondition){

  if ($i < 50){
    // Change values of your $dbt, $region and $uid varialbes here and concatenate the new statement to the existing $query var
    $query .='UPDATE `All` 
      SET `debt` = '$debt', `region` = '$region' 
      WHERE `uniqueid` = $uid; '
  } else {
    // Execute your update on your mysqli object then empty your $query and set $i to 0
    $mysqli->query($query);
    $query = '';
    $i = 0;
  }

  $i++;
}

从 50 开始,看看它是否提高了性能,如果提高了,就增加它。

您应该为 mysql 中的特定更新列添加索引,并在编程时放置包含这些 ID 的数组。 最后使用 ids IN 更新单个命令。

希望以上内容清楚!