有三种情况,即使你用了索引字段,mysql在执行sql的时候也不会走sql。
一,索引字段用函数
比如,create_time上使用了索引,但如下sql却不会走索引:
select * from t where month(t) = 7
原因是month(t)破坏了索引字段在索引树上的有序性,索引之所以快,就是因为索引在各层上是有序的。
二,隐式字段类型转换
如果索引字段my_id是varchar类型,如下sql不走索引:
select * from t where t.my_id = 1
因为在mysql中,字符串和数字比较时,字符串会变成数字,再比较。
这条sql相当于:
select * from t where cast(my_id as integer)=1
三,字符集不同
如果两个表的字符集不同,两个表进行关联时,哪怕关联字段是索引字段,mysql也要先进行字符串转换,字符串转换相当于使用了函数,所以也不走索引:
t1表:主键字段->id,字符集->utf8mb4
t2表:主键字段->id,普通索引字段->trade_id varchar(32),字符集->utf8
select t2.trade_sku from t1,t2 where t1.trade_id=t2.trade_id and t1.id=100
这条sql首先从t1中找出id为100的行的trade_id字段的值$value,然后执行
select * from t2 where trade_id = $value
此时$value的编码是utf8mb4,而t2的trade_id的编码是utf8,mysql会对trade_id进行编码转换:
select * from t2 where CONVERT(traide_id USING utf8mb4) = $value
对索引字段使用了函数,不会走索引。
优化方法1:
select * from t2 where CONVERT($value USING utf8mb4) = traide_id
优化方法2:
把t2的trade_id字段编码改为utf8mb4
alter table trade_detail modify tradeid varchar(32) CHARACTER SET utf8mb4 default null;