-
对于创建的多列索引(复合索引),不是使用的第一部分就不会使用索引
alter table student add index my_index(name, age) // name左边的列, age 右边的列 select * from student where name = 'aaa' // 会用到索引 select * from student where age = 18 // 不会使用索引
由于mysql中的联合索引是b+树的结构,联合索引(abc)会按照a先排序,再排b,最后排c,所以ab可以走到索引,ac只会走到索引a,bc是无序的,bc走不到索引。
例如 联合索引abc
(1,1,1),(1,2,3),(1,3,2)
-
对于使用 like 查询, 查询如果是 ‘%aaa’ 不会使用索引,而 ‘aaa%’ 会使用到索引。
select * from student where name like 'aaa%'
// 会用到索引select * from student where name like '%aaa' 或者 '_aaa' // 不会使用索引
-
如果条件中有 or, 有条件没有使用索引,即使其中有条件带索引也不会使用,换言之, 就是要求使用的所有字段,都必须单独使用时能使用索引。
-
如果列类型是字符串,那么一定要在条件中使用引号引用起来,否则不使用索引。
-
如果mysql认为全表扫面要比使用索引快,则不使用索引。
如:表里只有一条数据。
-
索引列上进行计算,会导致索引失效
select * from t_user where id + 1 = 2 ;
建议的使用方式是:先在内存中进行计算好预期的值,或者在SQL语句条件的右侧进行参数值的计算。
可以修改为
-- 内存计算,得知要查询的id为1
select * from t_user where id = 1 ;
-- 参数侧计算
select * from t_user where id = 2 - 1 ;
- 使用is not null
select * from t_user where id_no is not null;
使用is not null 会导致索引失效,查询条件使用is null时正常走索引,使用is not null时,不走索引。
- 索引列上使用函数
select * from t_user where SUBSTR(id_no,1,3) = '100';
使用字符截取函数会导致索引失效
是因为数据库要先进行全表扫描,获得数据之后再进行截取、计算,导致索引索引失效。同时,还伴随着性能问题。
示例中只列举了SUBSTR函数,像CONCAT等类似的函数,也都会出现类似的情况。解决方案可参考第三种场景,可考虑先通过内存计算或其他方式减少数据库来进行内容的处理。
9. order by导致索引失效
select * from t_user order by id_no ;
这一个主要是Mysql 自身优化的问题 我们都知道OrderBy 是排序 那就代表我需要对数据进行排序 如果我走索引 索引是排好序的 但是我需要回表 消耗时间 另一种 我直接全表扫描排序 不用回表 也就是
*
走索引 + 回表
*
不走索引 直接全表扫描
Mysql 认为直接全表扫面的速度比 回表的速度快所以就直接走索引了 在Order By 的情况下 走全表扫描反而是更好的选择
子查询会走索引吗答案是会 但是使用不好就不会