看啥推荐读物
专栏名称: 老骥
欢迎交流数据库相关技术知识<br>mysql...
今天看啥  ›  专栏  ›  老骥

MySQL 不能使用索引的情况总结 注意隐式转换的坑

老骥  · 简书  ·  · 2021-04-29 09:06

1、索引字段上加函数
select * from table where year(datefield) ='2020'
mysql 8.0版本已支持函数索引

2、索引字段上有表达式
select * from table where field + 2= N

3、like 使用了左匹配通配符
select * from table where field like '%aa'

4、联合查询 没有遵守左前缀匹配原则
alter table t add index idx_id_name(id,name)
select * from t where name = 'aaa'

5、or 条件一边字段有索引 而另一边字段没有索引

上面的5种很好理解,也不容易犯错。 下面讲一下隐式转换带来的问题

6、索引字段执行了隐式转换
有些隐式转换是能使用索引的,有些是不能使用的 下面一一来看一下
看测试数据

-- 构造测试数据1
CREATE TABLE `testconvert` (
`id` int NOT NULL ,
`numfield` int NOT NULL ,
`strfield` varchar(100) NOT NULL ,
`datefield` datetime NOT NULL ,
PRIMARY KEY (`id`)
)
;


insert into testconvert(id,numfield,strfield,datefield)
values(1,100,'100',cast('2020-10-01' as datetime )),
(2,200,'200',cast('2020-10-02' as datetime)),
(3,300,'300',cast('2020-10-03' as datetime ))

建立三个索引

alter table testconvert add index idx_num(numfield);
alter table testconvert add index idx_str(strfield);
alter table testconvert add index idx_date(datefield);
idx1.png

字段为数值型,比较值为字符型,会将字符串隐式转换为 数值型(官方说是转换为浮点数)。 所以数值型的索引就能起效

idx2.png

字段为字符型,比较值为数值型 会将字符串隐式转换为 数值型。 所以字符型的索引就能起效

idx3.png

字段为日期型 比较值为字符型 会将日期型与字符型都转换为时间戳 所以日期型的索引就能起效

我理解的隐式转换是否会引发索引失效的一个重要标准就是。如果发生了隐式转换 转换后索引的顺序依然有效(比如 第一种情况,将int转换为 浮点数 但int索引本身的顺序不会改变) 那么就能走索引

而第二个例子。 将字符字段 转为了浮点数 (字符串的顺序是 1<12<2 而浮点数的顺序是 1<2<12 ) 索引顺序发生了改变,所以索引就无效

日期型的转换官方贴了很多例外情况,大家可以看官方链接
https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html

总结,请尽量保持比较不发生隐式转换,可以自己显示转换。

比如上面失败的 改为这样


idx4.png

可以看到就可以走索引了




原文地址:访问原文地址
快照地址: 访问文章快照