explain
这是此次想要了解的重点命令,用于查看mysql
中查询sql语句的执行计划,用来对sql进行优化,以最合理的方式写sql语句
一条标准的sql查询语句:mysql
explain select id from user_customer where id=1\G;
获得的结果:sql
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: user_customer partitions: NULL type: const possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: const rows: 1 filtered: 100.00 Extra: Using index
从上面能够看到全部的参数,下面一一进行说明:服务器
select查询的标识符,每一个select都会被自动分配一个惟一的标识符mysql优化
select 查询的类型,常见的值以下:性能
SIMPLE:表示此查询不包含UNION查询或子查询优化
PRIMARY:表示此查询是最外层的查询ui
UNION:表示此查询是UNION的第二或随后的查询编码
DEPENDENT UNION:UNION中的第二个或后面的查询语句,取决于外面的查询code
UNION RESULT:UNION的结果排序
SUBQUERY:子查询中的第一个SELECT
DEPENDEND SUBQUERY:子查询中的第一个SELECT,取决于外面的查询,即子查询依赖于外层查询的结果
DERIVED:被驱动的select子查询(子查询位于FROM子句)
MATERIALIZED:被物化的子查询
查询涉及到的数据表或衍生表
type
字段比较重要,它标识了查询是否高效,是使用了全表扫描
仍是索引扫描
等等
system:表中只有一条数据,这个类型是特殊的const类型
const:针对主键或惟一索引的等值查询扫描,最多只返回一条数据。const查询的速度很是快,由于它仅仅读取一次便可,以下面的sql语句
select * from user_customer where id=5;
ref:此类型一般出如今多表的join查询,针对于非惟一或非主键索引,或者是使用了最左前缀
规则索引的查询
select * from user_customer where first_name='123' and last_name='456'; explain select * from migrations,user_customer where migrations.batch=user_customer.uid and cid>1\G;
eq_ref:一般出如今多表的join查询,对于对于前表的每个结果,都只能匹配到后表的一行结果,而且查询的比较操做是=
,查询效率较高
explain select * from migrations,user_customer where migrations.batch=user_customer.uid \G; //前表的数据在后表中都有匹配
range:range表示的索引范围查找,经过索引字段范围获取表中部分数据记录,这个类型一般出如今=
, <>
, >
, <
, between
, in()
等操做中
当type
是range
时,那么explain
输出的ref
字段为NULL,而且ken_len
字段为这次查询中使用到的索引的最长的那个
> int的长度是4字节,bigint的长度是8字节;字符串根据字段的长度能够计算出长度(**utf每一个字符占用3字节,若是是varchar**);若是字段容许null则会增长一个字节的大小
index:表示扫描的时候仅仅扫描了索引,而不扫描数据;也就是说在查询数据的时候直接在索引树中就能够获取到,在这种状况下的时候,extra字段会显式Using Index
all:表示全表扫描,是全部这些属性中性能最差的一个
all < index < range ~ index_merge < ref < eq_ref < const < system
表示在查询的过程当中有可能使用到的keys
表示查询优化器使用到了的索引的字节数,这个字段能够评估出组合索引是否被彻底使用到,或只有最左部分字段被使用到,key_len
的计算规则以下:
字符串
char(n):固定长度,n字符长度,根据不一样的编码n2或n3的字节
varchar(n):变长长度,在实际计算存储大小的时候,n小于255则用1字节存储长度,大于255则用2字节存储长度
数值类型
tinyint(n):1字节
smallint(n):2字节
mediumint(n):3字节
int(n):4字节
bitint(n):8字节
时间类型
date:3字节
timestamp:4字节
datetime:8字节
字段属性:
Null属性占用一个字节,若是字段是NOT NULL的,则不会占用这额外的一字节
在数值类型中,是预留出了一位去存储数值的符号
mysql查询优化器根据统计信息,估算sql要查找结果集须要扫描读取的数据行数,这个值能够直观的反映出sql的效率,原则上rows数值越小越好
在sql中不少额外的信息会在extra字段中体现:
Using filesort
当Extra字段中有Using filesort
时,表示mysql须要额外的排序操做,不能经过索引顺序达到排序效果;在sql语句中使用order by
进行排序的时候,若是没有很好的使用到定值和最左排序的话,会出现这种状况
Using index condition
这是mysql5.6的新特性,叫索引条件推送
,只是针对于二级索引。
在通常状况下,mysql服务器都会将存储引擎处理完成的数据返回给服务层后在应用where条件进行过滤,可是当mysql筛选到where条件中的第一个条件筛选的方式是相似于范围查询,就是like
,<
等;可是这里mysql的查询优化器会筛选第一个where条件中的可以查询出的范围,会根据range的范围与数据的总数进行对比进行什么样的查询
查询想要获取的字段都是*
Using index
“覆盖索引扫描”,表示查询在索引树上就能够找到所须要的数据,而不须要扫描底层的叶子节点数据,这种状况性能很好
只出现了这个的时候表示性能很好;若是这个和Using where
同时出现的话,表示先在存储引擎中使用索引进行筛选,再在mysql服务中进行条件筛选
Using temporary
在查询的时候使用临时表,通常出现排序,分组和多表join的状况,查询效率不高,建议进行优化
Using where
使用了where从句来限制哪些行将与下一个表匹配或者是返回给用户
Extra列出现Using where表示mysql服务器将存储引擎返回服务层之后再应用where条件过滤
有一种状况,数据表中数据量很大,查询的条件在数据表中占的比例也很高,原本在原则上可使用索引,可是由于该查询记录占表中比例很大,mysql会不对该sql使用索引,这种状况能够在查询语句后面使用limit
进行限制
Using MRR
这也是mysql5.6新增的特性, Multi-Range Read(多范围读),针对基于辅助/第二索引的查询,减小随机IO,而且将随机IO转换为顺序IO,提升查询效率
在基于mysql中的Innodb的数据存储方式才用的是B+tree
,二级索引的存储顺序与主键的顺序是不一致的,开启了mrr以后,mysql将根据辅助结果集获取的结果集根据主键进行排序,将乱序化为有序,能够用主键访问基表,将随机读转换为顺序读,多页数据记录可一次性读入或根据这次的主键范围分次读入,以减小IO操做,提升查询效率
Not exists
mysql优化了left join
,一旦它找到了匹配left join标准的行,就再也不搜索了