在巨大的 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 更新单个命令。
希望以上内容清楚!
这是我的 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 更新单个命令。
希望以上内容清楚!