Empty UPDATE方式比相应的SELECT慢

时间:2014-04-23 15:32:17

标签: innodb mysql-5.5 mysql-5.1 mysql-5.6

我正在使用带有InnoDB的MySQL 5.1.73

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

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,因此总DB大小约为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没有使用任何索引。所以问题仍然存在:为什么

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

1 个答案:

答案 0 :(得分:1)

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

总而言之,如果colcharcol被编入索引:

UPDATE table SET col=2 WHERE col=1

不会使用索引,因此,而

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

将使用索引,因此快速