索引失效与解决方案

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优化器就能把这次查询优化转化为一个常量。至于如何转化以及何时转化,这个取决于优化器。

以上是关于索引失效与解决方案的主要内容,如果未能解决你的问题,请参考以下文章

mysql 理解索引,添加索引,使用索引(哪些情况会导致索引失效)

Oracle 索引失效

oracle分析表,解决索引失效

MySQL优化:索引失效分析in与exists使用场合

MySQL高级 之 索引失效与优化详解

Oracle 索引失效的六大限制条件