我有一个包含大约 350 000 行的表,最近我从 MyISAM 存储引擎更改为 InnoDB。
我运行查询
UPDATE `users` SET `online` = 0
每次我的服务器启动时,使用 MyISAM 时都没有任何问题。该查询通常只影响几百行。查询的执行时间很慢,平均大约 1.5 秒,但我可以忍受。
现在我已经更改为 InnoDB,但是查询可能需要数十秒才能完成。
这是 mysql-slow.log 的一部分
# Query_time: 29.431546 Lock_time: 0.000091 Rows_sent: 0 Rows_examined: 348617
SET timestamp=1372505574;
UPDATE users SET online = 0;
这个特定的查询更改了 200 行的在线值,其他行已经是 0。
我能够通过将查询更改为来解决该问题
UPDATE `users` SET `online` = 0 WHERE `online` != 0
本次查询耗时约0.1秒
现在,这是我的问题。为什么从 MyISAM 更改为 InnoDB 时时间会显着增加?
为什么没有 WHERE 部分查询会这么慢?据我所知,MySQL 的查询优化器非常强大,但这表明事实恰恰相反。是什么导致查询执行时间非常慢?
MySQL服务器版本是5.5.31-0。
在InnoDB中,update
语句锁定它们扫描的每一行。这意味着要更新 200 行,它必须创建 350 000 个行级锁,同时保持回滚锁并向任何正在读取已更改值的事务提供先前的值(因为该事务不是已提交且更改不是最终的)
另一方面,MyISAM 锁定整个表。
因此,如果您需要更新所有行,则锁定整个表,您将获得更好的性能(您不需要行级锁)
但更好的是,提供一个 WHERE 子句,就像你所做的那样,InnoDB 将仅获取匹配行的锁(以及索引树中的一些间隙锁,但这超出了问题的范围)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)