1

我正在使用 MySQL 5.1.73 和 InnoDB

我有一个非常慢的 UPDATE 查询(大约 10 秒),其中更改的行数(通常)为零(如果有几行更改,则需要大约相同的时间):

UPDATE job_queue SET state=4 WHERE error_counter>=5 AND state=1;
Query OK, 0 rows affected (9.33 sec)

但是,相应的 SELECT 相当快:

SELECT id FROM job_queue WHERE error_counter>=5 AND state=1;
Empty set (0.03 sec)

EXPLAIN SELECT id FROM job_queue WHERE error_counter>=5 AND state=1;
+----+-------------+-----------+-------+--------------------------------------------+---------------------+---------+------+-------+--------------------------+
| id | select_type | table     | type  | possible_keys                              | key                 | key_len | ref  | rows  | Extra                    |
+----+-------------+-----------+-------+--------------------------------------------+---------------------+---------+------+-------+--------------------------+
|  1 | SIMPLE      | job_queue | index | Allinone,state_timeout,state_error_counter | state_error_counter | 5       | NULL | 13515 | Using where; Using index |
+----+-------------+-----------+-------+--------------------------------------------+---------------------+---------+------+-------+--------------------------+

如您所见,这是(应该是?)一个索引查询,在一个不太大的数据库上(大约 9000 行,虽然它确实包含一些 blob,所以总数据库大小约为 800MB)。

问题是:

  • 为什么更新这么慢?
  • 我该如何调试它?
  • 我怎样才能加快速度?

更新:我在使用 MySQL 5.5.35(Debian wheezy 默认)的不同服务器上尝试了相同的数据库。查询还是快,更新还是慢,更新还是没有解释……我可能会尝试从dotdeb升级到mysql 5.6,或者试试mariadb。:)

更新 2:我尝试了不同的行格式(动态和压缩),但也没有(明显)更快。

更新3:我更新到MySQL 5.6.17(来自dotdeb),性能大体相同,但我终于得到了更新的解释:

EXPLAIN UPDATE job_queue.job_queue SET state=4 WHERE error_counter>=5 AND state=1;
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+-------------+
| id | select_type | table     | type  | possible_keys | key     | key_len | ref  | rows  | Extra       |
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+-------------+
|  1 | SIMPLE      | job_queue | index | NULL          | PRIMARY | 8       | NULL | 70222 | Using where |
+----+-------------+-----------+-------+---------------+---------+---------+------+-------+-------------+

这只证实了一直以来可能被怀疑的东西:UPDATE 没有使用任何索引。所以问题仍然存在:为什么

我将尝试创建一个产生这种行为的最小示例;也许在这个过程中,我会找到一些答案......

4

1 回答 1

1

我发现问题了!该state列定义为char(1)。有趣的是,包含state=1大多数时间的 SELECT 确实使用索引,但 UPDATE 从不使用。但是,指定state="1"总是使用索引。

所以总而言之,如果col是一个char并且col被索引:

UPDATE table SET col=2 WHERE col=1

不会使用索引,因此速度很,而

UPDATE table SET col=2 WHERE col="1"

将使用索引,因此速度很快

于 2014-04-24T11:16:51.047 回答