mysql执行计划

执行计划分析

什么是执行计划?

select * from  city where sname='张飞';

分析的是优化器按照内置的代价计算模型算法,

最终选择后的执行计划。



cost ? 代价,成本

对于计算机来讲,代价是什么?

io,cpu,mem 

查看执行计划 

mysql> explain select * from world.city;

+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+

| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |

+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+

|  1 | SIMPLE      | city  | NULL      | ALL  | NULL          | NULL | NULL    | NULL | 4046 |  100.00 | NULL  |

+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+

1 row in set, 1 warning (0.00 sec)

执行计划显示结果的分析

table  :此次查询涉及到的表

type  :查询类型:全表扫,索引扫

possible_keys :可能会用到的索引

key :最后选择的索引

key_len :索引的覆盖长度 

rows :此次查询需要扫描的行数

Extra :额外的信息


详细分析

table:此次分析所涉及到的表,多对查询时,定位到有问题的表

type 查询类型

全表扫描 : 不会利用到所有的索引 ALL 

例如:select * from city;

select * from city  where sname = like '%y%';

select * from city  where sname not in  '张飞';

索引扫描 : index  < range < ref < eq_ref < const(system)

index :全索引扫描 

desc select contrycode from world ;contrycode有索引

range:索引范围查询: > < >= <= like in or between and 

desc select countrycode from world.city where id > 10;

desc select countrycode from world.city where countrycode  like 'F%';

desc select * from city where countrycode in ('USA','CHN');

特殊情况:查询条件为主键是可以走range 范围查询

!= 和 not in  会自动拆分为范围查询

ref :  辅助索引的等值查询 

desc select * from city where countrycode = ('USA');

eq_ref :多表链接中,非驱动表的链接条件是主键或唯一键.

a join b  on a.xx = b.yy  

desc select c.name,l.name from city c join country l

on c.`CountryCode` = l.`Code` where c.`Name`='Shanghai';

const(system):聚簇索引等值查询。

desc select * from city where id=1;

possible_keys 可能用到的索引,所有和此次查询有关的索引情况

key:当次查询选择的索引

key_len :联合索引的覆盖长度

例如:index(a,b,c) 我们希望我们的查询,对联合索引,应用的越充分越好,

key_len可以帮我判断,此次查询走了联合索引的几部分.

假设,某条查询可以完全覆盖三列联合索引

select  * from t1 where a=  and b =  and c = 

ken_len = a长度 ? + b长度? + c长度?

长度受到 数据类型  字符集 影响  

长度指的是,列的最大的字节存储长度

数字:

         not null     没有not null  

tinyint  1字节     1+ 1 

int  4字节           4+ 1 

bigint  8字节      8 + 1 

key_len:

a int not null --->4

a int     ---->5


字符: utf8------->一个字符最大占3个字节

                        not null       没有not null

 char(10)            3* 10          3*10 +1 

varchar(10)      3* 10 + 2(最多占用2个字节存储字符的长度)          3*10 + 2+ 1 

b char(10) not null 30 

b char(10)               31 

c varchar(10) not null 32 

c  varchar(10)     33  

字符: utf8mb4------->一个字符最大占4个字节

                        not null       没有not null

 char(10)            4* 10          4*10 +1 

varchar(10)      4* 10 + 2(最多占用2个字节存储字符的长度)          4*10 + 2+ 1 

b char(10) not null 40 

b char(10)               41 

c varchar(10) not null 42 

c  varchar(10)     43  

create table t1 (

a int not null ,

b int,

c char(10) not null,

d varchar(10) ) engine = innodb charset=utf8mb4;

alter table t1 add index idx_abcd(a,b,c,d);

desc select a,b,c,d from t1 where a= 1 and b = 3 and c = 'd' and d = '4';

1 SIMPLE t1 NULL ref idx_abcd idx_abcd 92 const,const,const,const 1 100.00 Using index

Extra 

using filesort:表示此次查询使用到了文件排序操作,

说明此次查询的排序操作 order by group by distinct ...(可能有这些语句)

列子;

 desc select * from city  where countrycode='CHN'  order by   population  ;


可以看到,extra出现了using filesort ,这时我们通过添加where条件字段和population字段的联合索引看是否能解决此问题;

alter table city add index idx_c_p(countrycode,population);

 desc select * from city  where countrycode='CHN'  order by   population  ;


可以看到此问题已经解决。

索引应用规范

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

1.建表时一定要有主键,一般是个无关列

2.选择唯一性索引

3.在联合索引中,让唯一索引(重复值较少的列)作为最左边的键,可以更快速的来查询。

4.如果字段过长最好使用前缀索引.

5.索引数据不是更多更好

可能产生的问题:

1).磁盘空间增大

2).修改表时,对索引的重构和更新和麻烦,越多的索引,会使更新表的时间变慢

3).优化器的负担很重,会影响优化器的选择

6.删除不使用的或者很少使用的索引

(percona toolkit).py-duplicate-key-checker  工具可以查询到重复的索引

7.大表加索引,要在业务不繁忙的期间操作(8.0以前要锁表)

8.尽量少在经常更新值的列上加索引(update的列,这样容易索引失效)

9.建索引的原则:

1)必须要有主键,如果没有可以作为主键条件的列,创建无关列。

2)经常做为where条件列,order by group by join distinct的条件(业务:产品功能+用户行为)

3)最好使用唯一值多的列作为索引条件,如果索引列重复值较多,可以考虑使用联合索引。

4)列值长度较长的索引,我们建议使用前缀索引

5)降低索引条目,一方面不要创建没有用的索引,不常使用的索引清理,percona toolkit的工具.

6)索引维护要避开业务繁忙期

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

1 没有查询条件,或者查询条件没有建立索引

select * from tab; 全表扫描

select * from tab where 1=1 ;

在业务库中,特别是数据量比较大的表,

是没有全表扫描的需求。

对用户查看是非常痛苦的。

对服务器来讲是毁灭性的。

2.查询结果集是原表中的大部分数据,应该是15-30%,

查询的结果集,超过了总行数的25%,优化器就觉得没有必要

走索引。

原因是??? 跟数据库的预读能力有关,以及一些参数有关。彩蛋??

解决办法,如果业务允许,进行分批次查询,或者进行分页查询。

limit 查询。

如果不允许,尽量不要把这部分数据存储在mysql,可以放到redis这种类似的

内存数据库中.

3。索引本身失效,统计数据不真实.

索引和表都有自我维护的能力。

对于表内容的变化比较频繁的情况下,统计信息不准确,过旧,有可能出现索引失效的情况。

解决办法:重建索引.

现象:有一条sql语句平时查询很快,突然很慢,会是什么原因。

表跟新频繁,统计信息过旧,导致索引失效.

查看表和索引的统计信息:

select * from innodb_table_stats; 表的统计信息

select * from innodb_index_stats; 索引的统计信息

不是实时跟新。

表的实时跟新解决办法:多删除点才可以跟新。

所以解决办法是,重建索引。

4.如果函数作用在索引上,或者对索引列进行运算,运算包括(+,-,* ,/,!等)

5.隐式转换导致索引失效,这一点应当引起重视

这里我测试字符串转数字不会失效,只有数字转字符串就会失效。

6.<>,not in  不走索引(辅助索引)(聚簇会走)

单独的> < in 又可能走索引,也可能不走.

7.like '%_' 百分号在前面不走索引。

如有这种大量的需求可以用mongodb数据库


扩展:优化器针对索引的算法

1mysql索引的自优化-AHI(索引页的索引,自适应hash索引)

mysql的innodb引擎,能够创建的只有btree。

ahi作用:自动评估热的内存索引page,生成一个hash索引表,加速

索引读取的速度。

2.mysql索引的自优化 -Change buffer 

insert update delete  数据

对于聚簇索引会立即更新

对于辅助索引,不是实时更新

在innodb内存结构中,加入了insert buffer(会话),现版本叫change buffer

change buffer的功能是临时缓冲辅助索引需要的数据更新。

当我们需要查询新insert 的数据,会在内存中进行mege 合并,此时辅助索引就是最新的。

3 ICP 索引下推 

在引擎层再次根据索引进行过滤,减少磁盘的io。

例如 index(a,b,c) select * from t1 where a= and c= 

 在sql层只走部分索引a,到引擎层再次走索引过滤掉部分c的数据,

在进行磁盘数据读取,减少了磁盘的io.

所涉及的算法调优的参数:

 select@@optimizer_switch;

|index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on |

如何修改算法参数?

1).my.cnf 

2).set global  optimizer_switch='batched_key_access=on'

3).hints 在语句里加入  /*+   */  也就是oracle里面的hint 

4.MRR  muti range read 

mrr = on  mrr_cost_based = on(开启mrr需要关闭 mrr_cost_based)

set global  optimizer_switch='mrr_cost_based=off';

默认的辅助索引查询,会多次回表,产生随机io。

mrr 缓存一部辅助索引的id,然后进行排序,利用rowid buffer,然后进行一次或者

少次数的回表,减少回表次数以及随机IO;提高服务器的性能。

辅助索引 回表 >> 聚簇索引 

转换为

辅助索引 > sort id 回表  >聚簇索引 

5.SNLJ  多表关联优化的算法 

a join b on a.xx = b.y y where a.c = b.c 

for each row  in b {

for each row in b{

 a.xx = b.xx send to  client }

以上例子,可以通过left join 强制驱动表

6.BNLJ  多表关联优化算法 

a join b on a.xx = b.y y where a.c = b.c

将a表满足条件的数据一次性(使用块)跟b表比对,并返回,减少了

循环的次数。提高了效率。a为驱动表.

when


7 BKA 

BNLJ的基础上,也就是把a表的数据放到一个块中,然后在进行排序,然后在跟

b表进行关联,可以减少io次数,和随机io次数。优化非驱动表的关联辅助索引。

开启的方式  开启:MRR ,在开启BKA。













©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • mysql执行计划作为分析一条sql的执行效率的工具十分有效,通过explain关键字便可查看select语句的具...
    SawyerZhou阅读 12,563评论 0 11
  • mysql的开源和使用简单使得其成为目前主流的RDB的主流数据库,但是mysql的效率相比Oracle性能上有很大...
    时之令阅读 1,069评论 0 3
  • 1、MySQL语法 MySql提供了EXPLAIN语法用来进行查询分析,在SQL语句前加一个”EXPLAIN”即可...
    chen_chen_chen_阅读 302评论 0 0
  • 一、分析 数据规模限制查询速度。在查询前能否预先估计究竟要涉及多少行、使用哪些索引、运行时间呢?答案是肯定的,My...
    Djbfifjd阅读 2,444评论 0 6
  • 引言: 实际项目开发中,由于我们不知道实际查询的时候数据库里发生了什么事情,数据库软件是怎样扫描表、怎样使用索引的...
    chen_chen_chen_阅读 439评论 0 0