索引失效与解决方案
Posted _大木_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了索引失效与解决方案相关的知识,希望对你有一定的参考价值。
文章目录
可能导致索引失效的场景
1. 索引列不独立. 独立是指: 列不能是表达式的一部分, 也不能是函数的参数
例如:
where条件的左侧有计算
explain
select * from employees where emp_no + 1 = 10003;
此时的 explain 为 all
解决方案:
将 条件改到where条件的右面 :
explain
select * from exployee where emp_no = 10003 -1;
此时的explain 为 const
2. 使用了左模糊
例如:
explain * from employees where first_name like '%Geo%'
解决方案:
尽量避免使用左连接, 如果避免不了, 可以考虑使用搜索引擎去解决;
explain * from employees where first_name like 'Geo%'
3. 使用or查询的部分字段没有索引
例如: first_name 有索引, last_name 没有索引, 则如下语句不能使用索引
explain
select * from employees where first_name = 'Georgi'
or last_name = 'Georgi';
解决方案:
额外添加 or 条件的索引, 这时候数据库会默认的将两个索引合并, 避免了全表扫描.
4. 字符串条件为使用 ’ ’ 引起来
例: 字符串条件未使用 ’ ’ 引起来 (dept_no 为字符串)
explain
select * from dept_emp
where dept_no = 3;
结果type 为 all
解决方案: 添加 ’ ’ , 规范的编写 sql
5. 不符合最左前缀原则的查询
解决方案:
调整索引的顺序, 变成index(first_name, last_name)
6. 索引字段建议添加 NOT NULL 约束
单列索引无法存储null值, 复合索引无法存储全为null的值
查询时, 采用 is null 条件时, 不能利用到索引, 只能全表扫描
mysql 官方建议尽量把字段定义为 NOT NULL
解决方案:
把索引字段设置成 NOT NULL, 甚至可以把所有字段都设置为 NOT NULL, 并且为字段设置默认值
7. 隐式转换导致索引失效
在创建表的时候要尽量规范: 比如使用int 或者 bigint
8. 索引失效导致行锁升级为表锁
我们之前对session-1和session-2都进行了关闭自动提交.
set autocomit=0; 关闭自动提交
索引类型(常用的6种):
索引失效则为 all (全表扫描)
覆盖索引: 从索引中直接获取查询结果,要使用覆盖索引需要注意select查询列中包含在索引列中;where条件包含索引列或者复合索引的前导列;查询结果的字段长度尽可能少。
1. all
“全表扫描”,通常意味着你的sql语句处于一种最原生的状态,有很大的优化空间, 我们都要避免这样类型的查找,除非你不得不这样做。
2. index
这种连接类型只是另外一种形式的全表扫描,只不过它的扫描顺序是按照索引的顺序。这种扫描根据索引然后回表取数据,和all相比,他们都是取得了全表的数据,而且index要先读索引而且要回表随机取数据.
3. range
range指的是有范围的索引扫描,相对于index的全索引扫描,它有范围限制,因此要优于index。关于range比较容易理解,需要记住的是出现了range,则一定是基于索引的
。同时除了显而易见的between,and以及’>’,’<'外,in和or也是索引范围扫描。
4. ref
出现该连接类型的条件是: 查找条件列使用了索引而且不为主键和unique。
其实,意思就是虽然使用了索引,但该索引列的值并不唯一,会有重复。这样即使使用索引快速查找到了第一条数据,仍然不能停止,要进行目标值附近的小范围扫描。
但它的好处是它并不需要扫描全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内扫描。
5. ref_eq
ref_eq 与 ref相比牛的地方是,它知道这种类型的查找结果集只有一个?什么情况下结果集只有一个呢!那便是使用了主键或者唯一性索引进行查找的情况,比如根据学号查找某一学校的一名同学,在没有查找前我们就知道结果一定只有一个,所以当我们首次查找到这个学号,便立即停止了查询。这种连接类型每次都进行着精确查询,无需过多的扫描,因此查找效率更高,当然列的唯一性是需要根据实际情况决定的。
6. const
通常情况下,如果将一个主键放置到where后面作为条件查询,mysql优化器就能把这次查询优化转化为一个常量。至于如何转化以及何时转化,这个取决于优化器。
以上是关于索引失效与解决方案的主要内容,如果未能解决你的问题,请参考以下文章