Mysql Explain详解与索引实践

一、Explain简介

使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句。分析你的查询语句或是表结构的性能瓶颈

通过EXPLAIN,我们可以分析出以下结果:

  • 表的读取顺序
  • 哪些索引被实际使用到
  • 数据读取操作的操作类型
  • 表有大约有多少行被优化器查询

用法:在select语句前添加explain

二、Explain分析

1、id

select查询的序列,表示查询中执行select子句或操作表的顺序。id列越大执行优先级越高

2、select_typ

用来表示查询的类型,主要是用于区别普通查询、联合查询、子查询等的复杂查询

  • SIMPLE: 简单的select查询,查询中不包含子查询或者UNION
  • PRIMARY: 查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY
  • SUBQUERY :在SELECT或WHERE列表中包含了子查询
  • DERIVED: 在FROM列表中包含的子查询被标记为DERIVED(衍生),MySQL会递归执行这些子查询,把结果放在临时表中
  • UNION:在 union 中的第二个和随后的 select

Mysql Explain详解与索引实践_第1张图片

3、 table

表示 explain 的一行正在访问哪个表

4、type

表示的是查询使用了哪种类型;type包含的类型,依次从最优到最差分别

system > const > eq_ref > ref > range > index > ALL

一般来说,得保证查询达到range级别,最好达到ref

system:

表只有一行记录,这是const类型的特例,平时不会出现

const:

const用于比较主键索引或唯一索引。只要通过索引一次就找到了,只匹配一行数据

eq_ref:

主键索引 或 唯一索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录

ref:

对比 eq_ref,使用普通索引或者唯一性索引的部分前缀,可能会找到多条记录

index:

扫描普通索引,这种扫描不会从索引树根节点开始快速查找,而是直接对二级索引的叶子节点进行遍历,速度还是比较慢的。二级索引一般比较小,所以这种通常比ALL快一些

ALL:

全表扫描,扫描聚簇索引的所有叶子节点。效率最慢,这时候就需要增加索引来进行优化

explain select * from actor;

5、possible_keys

6、key

7、key_len

显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列

key_len计算规则如下:

字符串,char(n)和varchar(n),5.0.3以后版本中,n均代表字符数,而不是字节数,如果是utf-8,一个数字

或字母占1个字节,一个汉字占3个字节

char(n):如果存汉字长度就是 3n 字节

varchar(n):如果存汉字则长度是 3n + 2 字节,加的2字节用来存储字符串长度,因为varchar是变长字符串

数值类型

tinyint:1字节

smallint:2字节

int:4字节

bigint:8字节

时间类型

date:3字节

timestamp:4字节

datetime:8字节

如果字段允许为 NULL,需要1字节记录是否为 NULL

索引最大长度是768字节,当字符串过长时,mysql会做一个类似左前缀索引的处理,将前半部分的字符提取出来做引。

8、ref

9、rows

10、Extra

展示的是额外信息

  1. Using index:使用覆盖索引
  2. Using where:使用 where 语句来处理结果,并且查询的列未被索引覆盖;表示优化器需要通过索引回表查询数据
  3. Using index condition:查询的列不完全被索引覆盖,where条件中是一个前导列的范围;
  4. Using temporary:mysql需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的,首先是想到用索引来优化。
  5. Using filesort:将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的。
  6. Select tables optimized away:使用某些聚合函数(比如 max、min)来访问存在索引的某个字段是

三、索引用法

  1. 最左前缀法则
  2. 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
  3. 存储引擎不能使用索引中范围条件右边的列
  4. 尽量使用覆盖索引(只访问索引的查询(索引列包含查询列)),减少 select * 语句
  5. is null,is not null 一般情况下也无法使用索引
  6. mysql在使用不等于(!=或者<>),not in ,not exists 的时候无法使用索引会导致全表扫描< 小于、 > 大于、 <=、>= 这些,mysql内部优化器会根据检索比例、表大小等多个因素整体评估是否使用索引

你可能感兴趣的:(Mysql,数据库,sql,mysql)