公司线上项目一个库的cpu使用率总是偏高,经同事点拨,发现一处索引使用不当。
首先观察下面的表结构。
CREATE TABLE `live_calc_1b` ( `vid` varchar(100) NOT NULL, ... PRIMARY KEY (`vid`) )
再看下面的这个sql。
select * from live_calc_1b where vid = 14635808219671833713;
看似很普通的使用场景却暗藏隐患,发现了没?
正确的使用方式如下所示
select * from live_calc_1b where vid = '14635808219671833713';
两者看似差别仅在于vid对应的值是否被单引号括起来,但效率上却天差地别,接下来我们通过explain语句分析下两者的效率差距。
mysql> explain select * from live_calc_1b where vid = 14635808219671833713\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: live_calc_1b type: ALL possible_keys: PRIMARY key: NULL key_len: NULL ref: NULL rows: 117 Extra: Using where 1 row in set (0.20 sec) mysql> explain select * from live_calc_1b where vid = '14635808219671833713'\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: live_calc_1b type: const possible_keys: PRIMARY key: PRIMARY key_len: 302 ref: const rows: 1 Extra: NULL 1 row in set (0.20 sec)
查询结果的key字段表示用到的索引,后者用到了主键索引,前者没使用索引。这也意味着前者是通过遍历全表找到结果的。
公司的线上环境数据库中的数据量很大,另外出现问题的地方也是一个update语句,为了方便在本文中使用select演示,但原理是一样的。修正之后,cpu利用率降低了一个数量级。
造成这种现象的原因是where语句查询时,数据类型不匹配造成的。若主键是int类型,而查询时使用字符串,也会引发相同问题。