目录
1.4、type:索引类型 system > const > eq_ref >( ref > range )> index > all
1.5、 possable key: 可能用到的索引-key
1.6、key:实际用到的key;如果为null,则没有使用索引
前言
explain(Execution plan cost)就是优化器做的事情。执行计划,很重要!!
只有明白sql是如何执行的,才能更好的优化,先了解它,然后才能优化它,explain就是和mysql优化对话的大门和打开优化器门的钥匙~
问题导读:
-
MySQL一定是按照我们输入的sql执行的吗?
-
如果不是,那么是如何优化和选择索引的呢?
-
如何知道MySQL使用了我们创建的那个索引,扫描的行数及是否排序情况?
1、认识explain
认识explain:可以模拟mysql优化器来执行sql语句,从而让我们知道db是如何执行sql的。分析sql和表结果的性能瓶颈。
实操,
语法:
explain +sql

1.1、Id:表的读取顺序
Id
:查询的序列号,一组数字,表示查询中执行的select字句或操作表的顺序
-
相同:自上而下
-
不相同:id号越大优先级越高,先执行;
-
相同又不同的子查询顺序满足1-2, 小表驱动大表;


1.2、Select_type: sql的操作类型
Select type
:
查询类型,主要用于区别 普通查询/联合查询/子查询等的复杂查询
-
Simple:简单的select查询,查询中不包含子查询或者UNION
-
Primary: 查询中包含任何复杂的字部分,最外层查询被标记为:
-
SUBQUERY: select或where中包含的子查询
-
Deriverd: 在from中包含的子查询被标记为driverd(衍生),不是真实的表;
-
Union:第二个selet出现union后将标记为nuion;
-
Union result:是对两个sql语句的结果的一个结果合并;



1.3、table:操作的表名称
table:显示这一行的数据属于那张表
1.4、type:索引类型 system > const > eq_ref >( ref > range )> index > all
type
:system > const > eq_ref >(
ref > range
)> index > all
System: 表只有一行记录,例如系统表;比如lock等待的时间query_lock_wait/long_query_time
const: 指常量查询比如 id = 1 ,
使用主键或者唯一索引等值查询一次命中,因为只匹配一行;

eq_ref: 唯一索引命中,常见于主键索引和唯一索引扫描本表或者关联表,
非常量查询;通过唯一的索引值来匹配,表中只有一条记录与之匹配;

Ref:
查询索引,使用了条件索引,非唯一性索引。
返回一条或多条纪录,
非唯一性索引扫描,返回匹配某个单独值的所有行;本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,他可能会找到多个符合条件的行,所以它属于
查找和扫描的混合体。

range: 对索引使用了范围查询
,只检索给定范围的行,使用一个索引来选择行,key列显示使用那个索引。一般就是在你的where语句中出现
between/</>/in等查询的时候,这种
范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束另一点,不用扫描全部索引。

Ps:如果id不是表的 in 范围内的,就退化为all了。

Index:查询了所有索引的值
,只是不去扫描整个数据文件;
覆盖索引

all:标上没有索引,扫描所有的数据

1.5、 possable key: 可能用到的索引-key
案例:possible key为空,但是key使用了索引,实际上是用到了覆盖索引。
1.6、key:实际用到的key;如果为null,则没有使用索引

Ps: 注意一下possable_key没有值,key有值的情况;
1.7、Ken_len: 索引使用的字节数
key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引长度。在不损失精确性的情况下,长度越短越好;
-
显示的 值为索引字段的最大可能长度,并非实际使用长度,即 key_len 是根据表初定义计算而得,不是通过表内检索内容得出。
-
可以用来判断复合索引是否实效的关键指标。我们可以通过该索引的长度大小来看使用了那些索引。
-
char 和 vchar类型:latin 占用1个字节 ,gbk 占用2个字节, utf8 占用 3 个字节
字节大小的计算:
-
char(10) null 30 + 1;
-
varchar(10) + null 30 + 2 (字段长度) +1
Utf-8和utf8mb4
-
为了获取更好的兼容性,应该总是使用 utf8mb4 而非 utf8.
-
对于 CHAR 类型数据,utf8mb4 会多消耗一些空间,根据 Mysql 官方建议,使用 VARCHAR 替代 CHAR。
小结:
-
复合索引有最左前缀的特性,如果复合索引能全部用上,则是复合索引字段的长度之和,这也可以用来判断复合索引是否部分使用,还是全部使用
-
Null都需要一个字节的额外空间来标识该字段是否为空,所以索引字段最好不要为null,因为null让统计更加复杂,并且需要额外的内存空间。
-
变长varchar字段需要额外的两个字段来存储是否为空和长度;
整数/浮点数/时间类型的索引长度:
-
Not null = 字段本身的字段长度
-
Null = 字段本身的字段长度 + 1 (因为需要有 是否为空的标记,这个标记需要占用一个字节 )
Datetime
在
5.6
中占用
5
个字节,
datetime
在
5.5
中字段长度为
8
个字节;
1.8、Ref:表之间的引用
ref:显示索引的
具体那一列被使用了。
⚠️:
和type=ref区分开

1.9、rows:扫描的记录行数
rows:根据表统计情况及索引选用情况,大致估算出找到所需的记录所需要扫描的行数;
尽量少。
filtered:得到的结果数据和全部扫描的数据的一个百分比,大约不精确,
越大越好:
-
例如:70%表示扫描了100行共得到70行有效数据;
2.0、extra:额外信息
-
using filesort: 排序可以优化。mysql无法利用索引完成数据的排序;不是按照表内索引顺序读取数据, 无法利用索引的排序称为:文件排序 ,可能在 次磁盘-(外排序) 或者 内存(内排序)上完成排序,应尽量避免此种情况;
-
using temporary:mysql 使用了临时表来保存中间结果,常见于排序order by和组查询group by,distinct;
-
Using index: 使用了索引的排序, 使用了覆盖索引,避免了 回表 ;
-
using where:表明server使用了 where过滤;
-
using join buffer:使用了连接缓存; select price from order o INNER JOIN coupon c on o.id = c.orderid;
-
impossible where:where子句的值总为false,select * from goods where 1=2;
-
use index condition( push down) 使用了 索引下推;
extra实例操作演示:
临时表:

排序:

添加索引:
ALTER TABLE `kinginfo`.`goods` ADD UNIQUE INDEX `create_time_UNIQUE` (`create_time` ASC);

2、结束
认识优化器后,才能更好的掌握sql的执行过程,从而找到优化的点。
水滴石穿,积少成多。学习笔记,内容简单,用于复习,梳理巩固。
##参考资料,
《Innodb存储引擎》
《MySql实战详解》