第六章· MySQL索引管理及执行计划

Posted by

一、索引介绍

1.为什么要做索引

让获取的数据更具有目的性,从而提高数据库检索数据的性能

2.索引类型介绍

1)BTREE:树索引 B+树索引 B*树索引
2)HASH:HASH索引
3)FULLTEXT:全文索引
4)RTREE:R树索引

innodb存储引擎使用BETREE

tree索引一个节点是一次I/O

mysql5.6/5.7用的tree和b+tree

2.1:树索引

树索引与B+树索引对比

​ 1.与tree算法在查单点数据上I/O相同

​ 2..优化了范围查询

​ 3.在叶子节点添加了相邻节点的指针

2.2:B+树索引

2.3:B*树索引

3.索引管理

索引建立在表的列上(字段)的。
在where后面的列建立索引才会加快查询速度。
pages<—索引(属性)<—-查数据。

3.1:索引分类

主键索引

​ 创建语法:alter table 表名 add primary key 定义索引名(对添加索引的列名);

普通索引

​ 创建语法:alter table 表名 add index 定义索引名(对添加索引的列名);

唯一索引

​ 创建语法:alter table 表名 add unique key 定义索引名(对添加索引的列名);

3.2:添加索引

#添加普通索引
mysql> alter table student4 add index idx_name(name);

#查看表结构看索引
mysql> desc student4;
#查看建表语句,看索引
mysql> show create table student4;
#查看索引
mysql> show index from student4;
        key_name(索引名)  column_name(索引的列名)  index_type(使用的算法)

#删除索引
mysql> alter table student4 drop index idx_name;

#添加主键索引
mysql> alter table abc add primary key pri_id(id);

#添加唯一索引
mysql> alter table student add unique key uni_age(age);

注意:添加唯一索引前需要先去重看数据是否唯一

#计算某列有多少行数据
mysql> select count(name) from student2;

#去重
mysql> select distinct(name) from student2;

#去重后计算某列有多少行数据
mysql> select count(distinct(name)) from student2;

3.3:前缀索引和联合索引

注意:添加索引会占据磁盘空间,需避免对大列建立索引,默认情况是按照BTREE算法排序,若必须要建立索引,可以选择给其加前缀,以减少索引所需的时间

应用场景:如需对列中较长的数据加索引,如对博客系统中的博文加索引

前缀索引

根据字段的前N个字符建立索引

alter table 表名 add index 定义索引名(对添加索引的列名(前缀字符数));

#添加前缀索引(以前四个字符为建立索引)
mysql> alter table student3 add index idx_name(name(4));

联合索引

多个字段建立一个索引(查询时有顺序要求)

例:
where a.女生 and b.身高 and c.体重 and d.身材好
index(a,b,c)
特点:前缀生效特性
a,ab,ac,abc,abcd 可以走索引或部分走索引
b bc bcd cd c d ba … 不走索引

#添加联合索引:对多个字段创建索引(如对age,sex,date创建索引 索引顺序为创建时的顺序 )
mysql> alter table student3 add index idx_all(age,sex,date);

总结:

​ 1)需严格按照创建索引时的SQL语句中的索引顺序查询才可生效索引

​ 2)创建联合索引前需先调查用户查询数据的需求量再进行添加联合索引

二、explain详解

explain命令使用方法

语法:explain 查询语句;

mysql> explain select name,countrycode from city where id=1;
    type(索引扫描类型)

explain命令应用

查询数据的方式

1.全表扫描:

​ 1)在explain语句结果中type为ALL

​ 2)什么时候出现全表扫描

​ a)业务确实要获取所有数据

​ b)不走索引导致的全表扫描

​ c)没有索引

​ d)索引创建有问题

​ e)语句有问题

生产中,mysql在使用全表扫描时的性能是极其差的,所以MySQL尽量避免出现全表扫描

mysql> explain select * from city where district='heilongjiang';

2.索引扫描

常见的索引扫描类型:

​ 1)index
​ 2)range
​ 3)ref
​ 4)eq_ref
​ 5)const
​ 6)system
​ 7)null

从上到下,性能从最差到最好,性能至少要达到range级别

index:Full Index Scan,index与ALL区别为index类型只遍历索引树。

mysql> alter table city add index idx_dis(district);
mysql> explain select District from city;

range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行。显而易见的索引范围扫描是带有between或者where子句里带有<,>查询。

mysql> alter table city add index idx_pop(population);
mysql> explain select * from city where population>30000000;

mysql> alter table city drop index idx_pop;
mysql> explain select * from city where population>30000000;

ref:使用唯一索引扫描或者唯一索引的前缀扫描,返回匹配某个单独值的记录行。

mysql> alter table student3 add index idx_name(name(4));
mysql> explain select * from student3 where name='bgx';

1553168100541

1553167736220

eq_ref:类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件A

const、system:当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。

如将主键置于where列表中,MySQL就能将该查询转换为一个常量(主键或唯一建)

1553167477805

NULL:MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。

1553169879889

Extra(扩展)
Using temporary
Using filesort 使用了默认的文件排序(如果使用了索引,会避免这类排序)
Using join buffer

如果出现Using filesort请检查order by ,group by ,distinct,join 条件列上没有索引

mysql> explain select * from city where countrycode='CHN' order by population;

1553170412959

当order by语句中出现Using filesort,那就尽量让排序值在where条件中出现

mysql> alter table city add index idx_pop(Population);
mysql> explain select * from city where population>2870300 and countrycode='CHN' order by population;
mysql> explain select * from city where population=2870300 and countrycode='CHN' order by population;

1553170825726

1553170619826

key_len(索引长度): 越小越好

前缀索引去控制

rows(行数,与结果集相关): 越小越好

案例:优化rows

一:

1553171289013

mysql> alter table city add index idx_name(name);

1553171410111

二:案例场景:比如说在电商平台中,商品索引展示,商品过多影响查询速率,可以使用索引加limit

查询结果集是原表中的大部分数据,应该是25%以上才能走索引

1553172564826

解决:

1553172697278