MySQL 复习笔记(一)------ 索引 [3/3]

310 阅读4分钟

MySQL 复习笔记(一)------ 索引 [1/3] - 掘金 (juejin.cn)

MySQL 复习笔记(一)------ 索引 [2/3] - 掘金 (juejin.cn)

1 索引失效情况

1.1 最左前缀法则

定义:如果使用了联合索引,要遵循最左前缀法则。其是指索引从索引的最左列开始,并且不跳过索引中的列。如果跳过了,则部分索引失效(后面的索引失效)

例如创建了一个联合索引:

create index idx_name_sex_age on user(name,sex,age)

要想使用到该索引,就得保证最左侧的列(user列)存在,并且假设当前该表只有这一个索引(不考虑其他索引对这三个字段的影响)

1. 当查询语句为:

select * from user where name = '张三' and sex = '男' and age = 18

索引全部生效


2. 当查询语句为:

select * from user where name = '张三' and sex = '男' 

部分索引生效,但是age索引没有用到


3. 当查询条件为 :

select * from user where name = '张三' age = 18 

部分索引生效,sex 和 age 的索引没有用到,因为中间跳过了sex字段,导致age索引也失效

4. 当查询条件为 :

select * from user where sex = '男' and age = 18

不使用索引,使用全表扫描

1.2 索引列运算

不要在索引列上进行运算,否则该列索引将失效

例如:

select * from user where substring(phone,10,2)='15'

获取手机号后两位是15的行。

此时索引会失效。

1.3 字符串不加引号

查询的列如果是字符串并且不加引号,导致索引失效

例如:

select * from user where name = '张三'

select * from user where name = 张三

其查询的结果都是一样的,但是在不加引号的时候发生了隐式类型转换,导致索引失效

1.4 模糊匹配

如果仅仅是在尾部加了%,则索引仍然生效。

如果是在中间或者前面加了%,则索引失效。

例如:

select * from user where name = '张%'

select * from user where name = '%三'

第一条会走索引,第二条不会

1.5 or连接

如果or连接的条件前后字段都有索引,则索引生效

如果or连接的条件存在一个没有索引,则整个查询语句不走索引

例如 假设 id有索引,phone有索引,name没有索引:

select * from user where id = 1 or phone = '13800138000'

select * from user where id = 1 and name = '张三'

则第一条会走索引,第二条不会

1.6 其他情况

  1. 数据分布情况:如果MySQL认为全表扫描比使用索引的效率更高,则不走索引

  2. 如果某个字段有多个索引,则MySQL会自动选择合适的那一个索引

2 索引使用规则

2.1 SQL提示

SQL提示简单来说是在SQL语句中加入一些认为的提示来达到优化操作的目的

use index

select * from user use index(idx_name) where name = '张三'

建议Mysql使用idx_name索引来执行这条sql语句,但最终怎么使用还是Mysql说的算



ignore index

select * from user ignore index(idx_name) where name = '张三'

告诉MySQL在执行的时候不使用idx_name这条索引


force index

select * from user force index(idx_name) where name = '张三'

告诉MySQL在执行的时候强制使用idx_name这条索引

2.2 覆盖索引

尽量使用覆盖索引(查询使用了索引,并且需要返回的列在该索引中能找到),减少select *

假设 id 是聚集索引,phone是二级索引

select id,phone from user where phone = '13800138000'

由B+Tree的结构可以知道,当用phone查询到对应的id,从而不需要再进行回表查询

使用explain 查看执行结果可以看到extra列中的内容:

using index condition :查找使用了索引,但是需要回表查询数据

using where;using index :查找使用了索引,但是需要的数据都在索引列中能找到,不需要回表查询数据

2.3 前缀索引

当字段类型为字符串(varchar,text等)时,有时候需要索引很长的字符串,会让索引变得很大,查询时浪费时间,此时可以只将字符串的一部分前缀建立索引,大大节约索引空间。

例如:

create index idx_phone on user(phone(5))

对phone列的前5个字符建立索引。

但是如果有相同的值,会一条条的进行比对。(PS:在单列索引中,如果只有一列有索引而另一列没有索引,则会回表查询)