运维

MySQL索引及执行计划

2020-03-10  本文已影响0人  麟之趾a

索引的简介

类似于一本书的目录,起到优化查询的内容

索引的分类

BTREE 索引的演变

BTREE 索引原理图.png

上层节点存放下层节点的最小值,即根节点存放枝节点的最小值,枝节点存放叶子节点的最小值
BTREE+树在叶子节点增加了双向指针,BTREE*是在叶子节点和枝节点增加双向指针

辅助索引(二级索引)

1 .管理员选择一个列建立辅助索引
2 .MySQL自动将此列取出来
3 .将此列值排好序(从小到大)
4 .将排好的数据均匀的分配到叶子节点上
5 .生成枝节点和跟节点
6 .在叶子节点中的值,都会存储主键ID

聚集索引

1 .如果用的是辅助索引,拿到辅助索引叶子节点的聚集索引的ID值,去遍历,然后去查找数据
2 .MySQL会自动选择主键,作为聚集索引,没有主键会选择唯一主键,如果都没有会生成隐藏的
3 .MySQL进行存储数据时,会按照聚集索引列的值的顺序,有序的存储数据行
4 .聚集索引直接将原表数据页,作为叶子节点,然后提取聚集索引列向上生成枝节点和根节点

辅助索引细分

索引树高度问题

索引树高度一般越低越好,一般维持在3-4层最佳

数据行多的时候

采用分布式架构,进行分库分表

字段长度

尽量选择,字符串长度短的列作为索引列,如果业务不允许,则采用前缀索引

数据类型

char 和varchar的选择,enum的选择

关于索引操作的问题

查询索引

desc 表名;
PRI ===> 主键索引(聚集索引)
MUL===> 普通索引(辅助)
UNI====> 唯一索引
show index from 表名;   //查的比较全

创建索引

# 创建普通索引
alter table city add index idx_name(name)
这也是属于DDL语句,也会锁表。在业务不繁忙时间做,或者使用pt-osc工具
# 创建联合索引
alter table city add index idx_c_p(countrycode,population);
# 建立唯一索引
alter table city add index uniqe uniqx_dis(district);
注: 唯一索引列的值必须是唯一的,不能有重复值
# 建立前缀索引
alter table city add index idx_dis(district(5))

执行计划分析

作用

将优化器选择后的执行计划,给截取出来,给管理员判断执行效率。(在语句执行之前,把执行计划拿到)

获取执行计划

desc sql语句;
explain sql语句;

分析执行计划

table

表名,如果是多表连接,可能一个表出现问题,此时这个table就有作用了

type 重要

查询类型,MySQL查询中有两大类型 全表扫描和索引扫描
索引扫描的级别为: index,range,ref,eq_ref,const(system),null 从左到右的性能依次变好

possible_key

可能会用到的key

key

最后用到的key

key_len

索引覆盖长度,当前列可以为空时,其中有一个字节标识是否为空

单列索引长度

注: 所有列的可以为空,utf8mb4的字符集

varchar(20) 说明

int(5)   ===>   4+1 ==》  1 为标识该列是否为空
char(2) ===> 4+4+1  ==》 1 为标识该列是否为空
varchar(2) ===> 4+4+1+1+1 ===>   1 为标识该列是否为空  其余两个1位开始位置和结束位置

联合索引

add index idx(a,b,c,d)

cda  ==> a,c,d 只走a索引,因b没有了。建立联合索引的时候是按照a,b,c,d的顺序建立的===>优化建议,可以删除原来索引,在新建一个cda的索引。(在业务支持的情况下)
所有列相同的不同的索引会相互影响。
…… where  a=1 and b>3 and c=2 and d=5   如果出现不等值查询,索引只会卡在b那,即走a和b的索引
优化建议:
1 .把不等值查询放在最后面(不过优化器会自动排序)
2 .更改联合索引的顺序,删了重新建(重点)

Extra

额外执行的命令
重点: using filesort额外的排序 ,出现此语句,说明select排序的条件列中,没有合理的用到索引,涉及到排序的条件order by,group by,distinct,union

索引的应用规范

建立索引的原则(DBA的运维规范)

不走索引的情况(开发规范)

CREATE TABLE ttt(id INT,num CHAR(2))
INSERT INTO ttt VALUES(1,2),(2,'3');
ALTER TABLE ttt ADD INDEX idx(num)
DESC SELECT * FROM ttt WHERE num=2   //不走索引
DESC SELECT * FROM ttt WHERE num='2' //走索引
num=2 ,MySQL会通过函数将2 转换为字符串类型,根据上一条,索引列有函数,将不会走索引

联合索引,意外情况

将表中所有列建立联合索引,每个列作为查询条件都会走索引

上一篇 下一篇

猜你喜欢

热点阅读