mysql 数据库DBA课程04_02 索引及执行计划

9、执行计划分析
    9.1、作用
    将优化器 选择后的执行计划 截取出来,便于管理员判断语句的执行效率。
    9.2、获取执行计划
    desc sql语句
    desc select * from city where name= 'Kabul';


    explain sql语句
    explain select * from city where name= 'Kabul'; #获取到的是一样的

    9.3、分析执行计划


    9.3.1、table #表名
    9.3.2、type #查询的类型

    全表扫描 : 显示All
    索引扫描 :index, range , ref, eq_ref ,const(system), NULL (从左到右,等级超高,性能越好)
    index:全索引扫描
    desc select countrycode from city;



range:索引范围扫描(>, <, >=, <=, between, and, or, in, like)
desc select * from city where id >2000;


对于辅助索引来讲,!= 和 not in 等语句是不走索引的
对于主键索引来讲,!= 和 not in 等语句是走 range





ref:辅助索引等值查询
desc select * from city where countrycode='CHN' union all select * from city where countrycode='USA'

eq_ref:多表连接时,子表使用主键或唯一列作为连接条件
A join B on A.x = B.y ##(y列,是B表的主键或者唯一列)



const(system):主键或者唯一键的等值查询
desc select * from city where id=100;



    9.3.3、possible_keys: 可能会用到的索引

    9.3.4、key:真正选择了那个索引

    9.3.5、key_len:索引覆盖长度,作用,判断 联合索引的覆盖长度,一般情况下,越长越好。




utf8mb4 最大的预留长度4
utf8 最大的预留长度3
gbk 最大的预留长度2
varchar(20)----utf8mb4字符集
能存20个任意字符
不管存储的是字符,数字,中文,都1个字符最大预留长度是4个字节
对于中文来讲,1个字符 占4个字节
对于数字和字母,1个字符占用大小是 1 个字节

select length(列) from test;




分别为每列创建一个索引
alter table test add index id(id);

alter table test add index k1(k1);

alter table test add index k2(k2);

alter table test add index k3(k3);

alter table test add index k4(k4);




key_len单列:(utf8mb4) 单列,索引长度越小越好

char类型的最大预留长度 + 1(是否允许空,not null 就不加,null 加1)

varchar 类型的最大预留长度 + 3(其中1,为null,保留,还有,开始:1,结束:1)















删除刚才创建的索引,重新创建一个联合索引。

alter table test drop index id;
alter table test drop index k1;
alter table test drop index k2;
alter table test drop index k3;
alter table test drop index k4;

alter table test add index idx(k1,k2,k3,k4);

联合索引:索引长度越大越好,越大说明用的索引越多。



联合索引应用细节:add index idx(a,b,c,d),第一个索引必须要存在

只要我们将来的查询,所有索引列都是等值查询条件下,无关排列顺序。原因是,优化器,会自动做查询条件的排列。唯一值多的列放在最左侧这样会过滤掉大部分的数据。

不连续的部分条件(但是,第一个索引[最左列]必须要在,如果不在,则不会走索引。)


在条件查询中没有最左列条件时,没有k1的查询,都是不走索引的,就是,你建立索引的时候,比如idx(k1,k2,k3,k4),查询条时,where 条件中,只有(k2,k3,k4),这样是不会走索引的。
cda------>(重新排列)acd ---->a (只走a的索引)-----优化(建索引 idx(c,d,a))



dba------>(重新排列)abd-----ab (只走ab的索引)-----优化(建索引 idx(d,b,a))



3、在where 查询中如果出现> < >= <= like 此类的查询条件。
desc select * from test where k1='aa' and k2>'中国' and k3='aaaa' and k4='中国你好';



怎么优化上面语句:
删除原来的索引
alter table test drop index idx;

重新创建一个索引
alter table test add index idx2(k1,k3,k4,k2);

把 >的条件放在最后
desc select * from test where k1='aa' and k3='aaaa' and k4='中国你好' and k2>'中国';



4、多子句(有group by 有order by)查询,应用联合索引
desc select * from test where k1='aa' order by k2;

alter table test add index idx3(k1,k2);






必须按照子句的执行顺序去建联合索引

9.3.6、extra: 重点关注 Using filesort(还需要额外的文件排序)

出现: Using filesort,说明在查询中有关排序的条件列没有合理应用索引。
(order by 、group by、distinct、union)会出现排序。关注key_len应用的长度,有没有走全。
explain(desc)使用场景(面试题)

你做过哪些优化?
你作过什么优化工具?
你对索引这块怎么优化的?
我们公司业务慢,请你从数据库的角度分析原因

mysql 出现性能问题,我总结有两种情况

a)、应急性的慢:突然夯住

应急情况:数据库hang(卡了,资源耗尽)
处理过程:
show processlist; 获取到导致数据库hang的语句
explain 分析 sql 的执行计划,有没有走索引,索引的类型情况
建索引,修改语句。
如果还是卡,考虑有可能是语句本身的问题,需要开发配合修改。

b)、一段时间慢(持续性的):

记录慢日志slowlog,分析slowlog 。
explain 分析 sql 的执行计划,有没有走索引,索引的类型情况
建索引,修改语句。
++++++++++++++++++++

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

(1)、建表必须要有主键,一般是无关列,自增长。
(2)、经常做为where 条件列 order by group by join on,distinct 的条件列建索引
(3)、最好使用唯一值多的列作为联合索引前导列,其他的按照联合索引优化细节来做。
(4)、列值长度较长的索引列,我们建议使用前辍索引。减少key_len:索引覆盖长度
(5)、降低索引条目,不要创建没有用的索引,不常使用的索引清理,sqlyog,表信息,找出多余索引
(6)、索引维护要避开业务繁忙期
(7)、小表(几百行,几千行)不建索引

不走索引的情况(开发规范)
(1)、没有查询条件,或者查询条件没有建立索引
    select * from city;
    select * from city where 1=1;

(2)、查询结果集是原表中的大部分数据,应该是25%以上。
    查询结果集超过原表中25%的数据,不走索引。

(3)、索引本身失效,统计数据不真实。(大量的对索引列更新数据)

    面试题:同一个语句突然变慢?

统计信息过旧,导致的索引失效。

(4)、查询条件使用函数在索引列上,或者对索引列进行运算,运算包括(+,-,*,/,!)等。

    where 后面的条件 有计算 不走索引



(5)、隐式转换导致索引失效



(6)、< >,not in 不走索引(辅助索引)

(7)、like "%aa" 百分号在最前面不走索引