首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按主键执行的MySQL UPDATE查询有时非常慢

按主键执行的MySQL UPDATE查询有时非常慢
EN

Stack Overflow用户
提问于 2009-07-02 14:41:02
回答 2查看 4.6K关注 0票数 4

在我们的网站上,一个特定的更新查询有时会运行得非常慢,并且会检查很多不必要的行。它按主键进行过滤,所以我认为MySQL总是只需要检查一行。

下面是MySQL的慢查询日志中的一些示例:

代码语言:javascript
复制
# Time: 090702 12:59:06
# User@Host: XXX[XXX] @ XXX [XXX]
# Query_time: 21  Lock_time: 0  Rows_sent: 0  Rows_examined: 500500
SET timestamp=1246532346;
UPDATE `folders` SET `folder_id` = '1705641', `updated_at` = now() WHERE `folders`.`id` = '1682995';
# Time: 090702 14:13:44
# User@Host: XXX[XXX] @ XXX [XXX]
# Query_time: 17  Lock_time: 0  Rows_sent: 0  Rows_examined: 16816745
SET timestamp=1246536824;
UPDATE `folders` SET `folder_id` = '417997', `updated_at` = now() WHERE `folders`.`id` = '1705956';
# Time: 090702 14:15:42
# User@Host: XXX[XXX] @ XXX [XXX]
# Query_time: 13  Lock_time: 0  Rows_sent: 0  Rows_examined: 16816719
SET timestamp=1246536942;
UPDATE `folders` SET `folder_id` = '1706267', `updated_at` = now() WHERE `folders`.`id` = '1705956';
# Time: 090702 16:07:43
# User@Host: XXX[XXX] @ XXX [XXX]
# Query_time: 499  Lock_time: 0  Rows_sent: 0  Rows_examined: 88668449
SET timestamp=1246543663;
UPDATE `folders` SET `folder_id` = '1707407', `updated_at` = now() WHERE `folders`.`id` = '1706992';

不过,查询的运行频率比这更高,所以它并不总是公开这种行为。此外,如果我手动运行相同的查询,它们运行得很好,并且立即返回。

我还验证了这个表,据我所知,它应该没有问题:

代码语言:javascript
复制
mysql> describe folders;
+------------------+-----------------------+------+-----+---------------------+----------------+
| Field            | Type                  | Null | Key | Default             | Extra          |
+------------------+-----------------------+------+-----+---------------------+----------------+
| id               | mediumint(8) unsigned | NO   | PRI | NULL                | auto_increment | 
| user_id          | mediumint(8) unsigned | NO   | MUL | NULL                |                | 
| folder_id        | mediumint(8) unsigned | YES  | MUL | NULL                |                | 
| created_at       | timestamp             | NO   |     | CURRENT_TIMESTAMP   |                | 
| updated_at       | timestamp             | NO   |     | 0000-00-00 00:00:00 |                | 
| modified_at      | timestamp             | NO   |     | 0000-00-00 00:00:00 |                | 
| name             | varchar(255)          | NO   |     | NULL                |                | 
| guest_permission | tinyint(3) unsigned   | NO   |     | 1                   |                | 
+------------------+-----------------------+------+-----+---------------------+----------------+
8 rows in set (0.00 sec)

mysql> show index from folders;
+---------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table   | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| folders |          0 | PRIMARY   |            1 | id          | A         |      760318 |     NULL | NULL   |      | BTREE      |         | 
| folders |          1 | user_id   |            1 | user_id     | A         |       69119 |     NULL | NULL   |      | BTREE      |         | 
| folders |          1 | folder_id |            1 | folder_id   | A         |      380159 |     NULL | NULL   | YES  | BTREE      |         | 
+---------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
3 rows in set (0.00 sec)

另一件事是,MySQL服务器有时会锁定并停止接受连接,每次发生这种情况时,我通常都会在日志文件中找到一个慢查询,就在故障发生之前。我在其他日志文件中看不到任何相关的错误消息,但MySQL重启会使其再次响应。

有没有人知道发生了什么,或者我可以检查哪些东西来缩小问题的范围?

编辑:我们在一台专用服务器上使用PHP5.0.51a,目前有6台运行MySQL 5.2.6并通过PDO连接到MySQL服务器的We服务器。所有的服务器都在运行Debian Lenny。所有all服务器上都会发生缓慢的查询。

编辑:以下是一个相关查询的解释,带引号和不带引号:

代码语言:javascript
复制
mysql> explain SELECT * FROM `folders` WHERE `folders`.`id` = '1682995';
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | folders | const | PRIMARY       | PRIMARY | 3       | const |    1 |       | 
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)

mysql> explain SELECT * FROM `folders` WHERE `folders`.`id` = 1682995;
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | folders | const | PRIMARY       | PRIMARY | 3       | const |    1 |       | 
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-07-24 15:17:45

我真傻。我忘记了folders表上有一些触发器,当然是其中一个触发器中的查询导致了我的问题……

还有一个额外的表tree,它维护文件夹之间的关联,当文件夹在层次结构中被删除或移动时,触发器会更新这些关联。在UPDATE触发器中,在添加新的引用之前,它必须删除该文件夹的所有现有引用。相关的DELETE查询开始如下:

代码语言:javascript
复制
DELETE FROM `tree`
  WHERE `folder_id` IN (
    SELECT `folder_id` FROM `children`
  )
  AND ...

children是一个临时表,我以前在其中存储了我需要的文件夹ID。现在,由于某些原因,MySQL不能优化这个查询,但是如果我使用RIGHT JOIN,它可以很好地工作:

代码语言:javascript
复制
DELETE `tree`.* FROM `tree`
  RIGHT JOIN children USING (folder_id)
  WHERE ...

由于我更改了这个查询,所以MySQL的慢查询日志仍然是空的,并且我们没有遇到任何MySQL锁定。

票数 1
EN

Stack Overflow用户

发布于 2009-07-02 14:43:51

这很奇怪,但我猜测这可能是因为您的id字段是int,但您传递的是一个字符串(带引号)。试着不使用字符串,看看它是否有帮助。

为了帮助弄清楚到底发生了什么,将查询更改为带有相同WHERE子句的SELECT,并通过EXPLAIN运行它。如下所示:

代码语言:javascript
复制
EXPLAIN SELECT * FROM `folders` WHERE `folders`.`id` = '1682995';
EXPLAIN SELECT * FROM `folders` WHERE `folders`.`id` = 1682995;

看看是否有区别。

More info on EXPLAIN

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1074801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档