Mysql高级优化知识笔记--索引的使用场合及失效场景

1.哪些情况需要创建索引

  • 主键自动建立唯一索引
  • 频繁作为查询条件的字段应该创建索引(where 后面的语句)
  • 查询中与其它表关联的字段,外键关系建立索引
A 表关联 B 表:A join B  。  on 后面的连接条件 既 A 表查询 B 表的条件。
所以 B 表被关联的字段建立索引能大大提高查询效率
因为在 join 中,join 左边的表会用每一个字段去遍历 B 表的所有的关联数据,相当于一个查询操作
  • 单键/组合索引的选择问题,who?(在高并发下倾向创建组合索引)
  • 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
  • 查询中统计或者分组字段

2.哪些情况不要创建索引

  • 表记录太少
  • 经常增删改的表
Why:提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。
因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件
  • Where条件里用不到的字段不创建索引
  • 数据重复且分布平均的表字段,因此应该只为最经常查询和最经常排序的数据列建立索引。
注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。

3.索引失效

  • 全值匹配我最爱
索引  idx_staffs_nameAgePos 建立索引时 以 name , age ,pos 的顺序建立的。全值匹配表示 按顺序匹配的
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July';(失效)
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25;(失效)
EXPLAIN SELECT * FROM staffs WHERE NAME = 'July' AND age = 25 AND pos = 'dev';
  • 最佳左前缀法则。如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。
 **and 忽略左右关系。**既即使没有没有按顺序 由于优化器的存在,会自动优化。
经过试验结论  建立了 idx_nameAge 索引  id 为主键
    1.当使用覆盖索引的方式时,(select name/age/id from staffs where age=10 (后面没有其他没有索引的字段条件)),
    即使不是以 name 开头,也会使用 idx_nameAge 索引。
    **既 select 后的字段 有索引,where 后的字段也有索引,则无关执行顺序。**
    2.除开上述条件 才满足最左前缀法则。
	 EXPLAIN SELECT * FROM staffs WHERE age = 25 AND pos = 'dev';(失效)
	 EXPLAIN SELECT * FROM staffs WHERE pos = 'dev';(失效)
  • 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
	EXPLAIN SELECT * FROM staffs WHERE left(NAME,4) = 'July';(失效)
  • 存储引擎不能使用索引中范围条件右边的列
 范围 若有索引则能使用到索引,范围条件右边的索引会失效
 (范围条件右边与范围条件使用的同一个组合索引,右边的才会失效。若是不同索引则不会失效)
  • 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *
  • mysql 在使用不等于(!= 或者<>)的时候无法使用索引会导致全表扫描
索引  idx_nameAgeJob
         idx_name
使用 != 和 <> 的字段索引失效
( != 针对数值类型。 <> 针对字符类型前提 where and 后的字段在混合索引中的位置比比当前字段靠后  
where age != 10 and name='xxx'  ,这种情况下,mysql自动优化,
将 name='xxx' 放在 age !=10 之前,name 依然能使用索引。只是 age 的索引失效)
  • is not null 也无法使用索引,但是is null是可以使用索引的(待考证)
  • like以通配符开头(’%abc…’)mysql索引失效会变成全表扫描的操作
 like ‘%abc%’  type 类型会变成 all
 like ‘abc%’ type 类型为 range ,算是范围,可以使用索引
  • 字符串不加单引号索引失效
 底层进行转换使索引失效,使用了函数造成索引失效

  • 少用or,用它来连接时会索引失效

在这里插入图片描述
在这里插入图片描述

4.使用索引建议

  • 对于单键索引,尽量选择针对当前query过滤性更好的索引
  • 在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。
    (避免索引过滤性好的索引失效)
  • 在选择组合索引的时候,尽量选择可以能够包含当前query中的where字句中更多字段的索引
  • 尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的

5.解决like '%字符串%'时索引不被使用的方法??(使用覆盖索引)

(1)建表:
CREATE TABLE `tbl_user` (
 `id` INT(11) NOT NULL AUTO_INCREMENT,
 `NAME` VARCHAR(20) DEFAULT NULL,
 `age` INT(11) DEFAULT NULL,
 email VARCHAR(20) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;


#drop table tbl_user

(2)插数据
INSERT INTO tbl_user(NAME,age,email) VALUES('1aa1',21,'[email protected]');
INSERT INTO tbl_user(NAME,age,email) VALUES('2aa2',222,'[email protected]');
INSERT INTO tbl_user(NAME,age,email) VALUES('3aa3',265,'[email protected]');
INSERT INTO tbl_user(NAME,age,email) VALUES('4aa4',21,'[email protected]');
INSERT INTO tbl_user(NAME,age,email) VALUES('aa',121,'[email protected]');


#before index

(3)没建立索引的分析
EXPLAIN SELECT NAME,age    FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
EXPLAIN SELECT id    FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
EXPLAIN SELECT NAME     FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
EXPLAIN SELECT age   FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
EXPLAIN SELECT id,NAME    FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
EXPLAIN SELECT id,NAME,age FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
EXPLAIN SELECT NAME,age FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
EXPLAIN SELECT *     FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
EXPLAIN SELECT id,NAME,age,email  FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
(4)设置复合索引
#create index
CREATE INDEX idx_user_nameAge ON tbl_user(NAME,age);
#DROP INDEX idx_user_nameAge ON tbl_user
#after index
EXPLAIN SELECT NAME,age    FROM tbl_user WHERE NAME LIKE '%aa%';(使用索引)
EXPLAIN SELECT id    FROM tbl_user WHERE NAME LIKE '%aa%';(使用索引)
EXPLAIN SELECT NAME     FROM tbl_user WHERE NAME LIKE '%aa%';(使用索引)
EXPLAIN SELECT age   FROM tbl_user WHERE NAME LIKE '%aa%';(使用索引)
EXPLAIN SELECT id,NAME    FROM tbl_user WHERE NAME LIKE '%aa%';(使用索引)
EXPLAIN SELECT id,NAME,age FROM tbl_user WHERE NAME LIKE '%aa%';(使用索引)
EXPLAIN SELECT NAME,age FROM tbl_user WHERE NAME LIKE '%aa%';(使用索引)
EXPLAIN SELECT *     FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
EXPLAIN SELECT id,NAME,age,email  FROM tbl_user WHERE NAME LIKE '%aa%';(全表扫描)
```

发布了18 篇原创文章 · 获赞 2 · 访问量 656

猜你喜欢

转载自blog.csdn.net/qq_34699995/article/details/99209173