MySQL更新花费(太)长时间
在我们的服务突然出现一些预期增长之后,一些更新需要非常长的时间,这些更新过去非常快,直到表格达到大约2毫米的记录,现在每个更新大约需要40-60秒MySQL更新花费(太)长时间,sql,mysql,optimization,Sql,Mysql,Optimization,在我们的服务突然出现一些预期增长之后,一些更新需要非常长的时间,这些更新过去非常快,直到表格达到大约2毫米的记录,现在每个更新大约需要40-60秒 update table1 set field1=field1+1 where id=2229230; Query OK, 0 rows affected (42.31 sec) Rows matched: 1 Changed: 0 Warnings: 0 以下是字段类型: `id` bigint(20) NOT NULL auto_incre
update table1 set field1=field1+1 where id=2229230;
Query OK, 0 rows affected (42.31 sec)
Rows matched: 1 Changed: 0 Warnings: 0
以下是字段类型:
`id` bigint(20) NOT NULL auto_increment,
`field1` int(11) default '0',
分析的结果,对于上下文开关,它是唯一一个在结果中似乎有较高数字的开关:
mysql> show profile context switches
-> ;
+----------------------+-----------+-------------------+---------------------+
| Status | Duration | Context_voluntary | Context_involuntary |
+----------------------+-----------+-------------------+---------------------+
| (initialization) | 0.000007 | 0 | 0 |
| checking permissions | 0.000009 | 0 | 0 |
| Opening tables | 0.000045 | 0 | 0 |
| System lock | 0.000009 | 0 | 0 |
| Table lock | 0.000008 | 0 | 0 |
| init | 0.000056 | 0 | 0 |
| Updating | 46.063662 | 75487 | 14658 |
| end | 2.803943 | 5851 | 857 |
| query end | 0.000054 | 0 | 0 |
| freeing items | 0.000011 | 0 | 0 |
| closing tables | 0.000008 | 0 | 0 |
| logging slow query | 0.000265 | 2 | 1 |
+----------------------+-----------+-------------------+---------------------+
12 rows in set (0.00 sec)
show create table table1;
explain select * from table1 where id = 2229230;
该表大约有250万条记录,id是主键,在另一个字段上有一个唯一的索引(不包括在更新中)
这是一张innodb表格
有没有关于原因的线索
是否有任何特定的变量可以帮助跟踪问题
是否有更新的“解释”
编辑:我刚刚注意到该表还有一个:
`modDate` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
说明:
+----+-------------+---------------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | table1 | const | PRIMARY | PRIMARY | 8 | const | 1 | |
+----+-------------+---------------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.02 sec)
如果id真的是主键,那么查询就不可能花费很长时间(除非您有很多id等于2229230?)。请运行以下两个SQL并发布结果:
mysql> show profile context switches
-> ;
+----------------------+-----------+-------------------+---------------------+
| Status | Duration | Context_voluntary | Context_involuntary |
+----------------------+-----------+-------------------+---------------------+
| (initialization) | 0.000007 | 0 | 0 |
| checking permissions | 0.000009 | 0 | 0 |
| Opening tables | 0.000045 | 0 | 0 |
| System lock | 0.000009 | 0 | 0 |
| Table lock | 0.000008 | 0 | 0 |
| init | 0.000056 | 0 | 0 |
| Updating | 46.063662 | 75487 | 14658 |
| end | 2.803943 | 5851 | 857 |
| query end | 0.000054 | 0 | 0 |
| freeing items | 0.000011 | 0 | 0 |
| closing tables | 0.000008 | 0 | 0 |
| logging slow query | 0.000265 | 2 | 1 |
+----------------------+-----------+-------------------+---------------------+
12 rows in set (0.00 sec)
show create table table1;
explain select * from table1 where id = 2229230;
更新:只是为了完成,还做了一个
select count(*) from table1 where id = 2229230;
我也可以推荐:
OPTIMIZE TABLE table1;
有时候你的桌子需要一点爱,如果它们增长很快,而你在一段时间内没有对它们进行优化,那么索引可能有点疯狂。事实上,如果你有时间(而且你有时间),投入进去是没有坏处的
REPAIR TABLE table1;
好的,经过几个小时的追踪,原因似乎是“重复索引”,我回答Keith的创建表有一个奇怪的组合:
- fieldx上的唯一键
- fieldx上的一个键
+1致Keith和Ivan,他们的评论帮助我最终找到了问题所在。帮助我的是将引擎从“innodb”改为“myisam”。 我对相似大小数据集的更新查询从100毫秒变为0.1毫秒 请注意,更改现有应用程序的引擎类型可能会产生后果,因为InnoDB具有更好的数据完整性,并且应用程序可能依赖于某些功能
对我来说,失去InnoDB是值得的,因为它在大数据集上的速度提高了1000倍。我也遇到了同样的问题,结果是由于表上的触发器。每当对我的表进行更新时,触发器都会更新另一个表,而这实际上是延迟造成的。在该表上添加索引修复了该问题。因此,请尝试检查表上的触发器。调试update语句时,与select语句版本相比,需要考虑的另一件事是: update语句是否在事务中执行
在我的例子中,一个事务将update语句的执行时间从极快变为极慢。受影响的行越多,性能损失越大。我的语句使用用户定义的变量,但不知道这是否是“问题”的一部分。什么是
field1
和id
字段类型?您可以尝试分析此队列。看到了吗?1行匹配,但零行受影响?是的,我实际上是用field1=field1运行的选择需要那么长的时间,还是很快?另外,硬编码新的field1值是否需要那么长的时间?是否有办法事先知道优化或修复是否会起作用?或者运行它们是唯一的选择?@webclimber-在本地运行会告诉您。请注意:在执行表修复操作之前备份表;在某些情况下,该操作可能会导致数据丢失。“。为了防止偶然发现这个答案,修复表适用于MyISAM、ARCHIVE和CSV表,而不适用于InnoDB。+1如果在该信息中抛出错误的表定义,则查看是否存在错误肯定会有所帮助。将应用程序从InnoDB更改为MyISAM可能会很危险。”。MyISAM在数据完整性方面几乎没有提供任何保证。好的一点,我将在我的回答中补充这一点,如果应用程序是由同时设置引擎类型的人进行的,那么很高兴知道在某些情况下,为了速度而牺牲数据完整性是可能的。