mysql sql查询过程分析之explain关键字

Mysql EXPLAIN只能解释SELECT语句,并不会对存储程序和INSERT,UPDATE,DELETE或其他语句做解释. 但5.5版本之后支持了Update等语句.

explain分析结果每个表在输出中只有一行,如果是2个表的联接,那么输出有2行.

我们先创建一个表,本文所有的实验都将基于该表来做分析.

创建表 learn_explain,DDL如下: 

-- ----------------------------
-- Table structure for learn_explain
-- ----------------------------
DROP TABLE IF EXISTS `learn_explain`;
CREATE TABLE `learn_explain` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `act_id` int(11) DEFAULT NULL,
  `publish_date` datetime DEFAULT NULL,
  `value` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `act_id-publish_date` (`act_id`,`publish_date`) USING BTREE,
  KEY `second_index` (`value`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of learn_explain
-- ----------------------------
INSERT INTO `learn_explain` VALUES ('1', '1', '2015-08-09 17:03:36', '100');
INSERT INTO `learn_explain` VALUES ('2', '2', '2015-08-09 17:03:52', '101');
INSERT INTO `learn_explain` VALUES ('3', '3', '2015-08-09 17:04:02', '103');
INSERT INTO `learn_explain` VALUES ('4', '4', '2015-08-09 17:04:13', '104');
INSERT INTO `learn_explain` VALUES ('5', '5', '2015-08-09 17:04:23', '105');
INSERT INTO `learn_explain` VALUES ('6', '6', '2015-08-09 17:04:35', '106');

数据库的存储引擎采用InnoDB,learn_explain表创建了如下索引:

主键索引: id

唯一索引:  <act_id,publish_date>

普通二级索引: value


先看看explain分析的结果:



1,  id 列: 编号, 标识SELECT所属的行。

2,  select_type:  分为简单(SIMPLE)和复杂类型.  

复杂类型又分为: 

2.1 简单子查询(SUBQUERY).

2.2 所谓的派生表(DERIVED)(在FROM子句中的子查询).

2.3 UNION查询(UNION).

2.4 UNION RESULT 用来从UNION的匿名临时表检索结果的SELECT标识为UNION RESULT.

3, type列. 访问类型,换言之就是MYSQL决定如何查找表中的行.

3.1 ALL 所谓的全表扫描. 按行查找(不是按索引查找).

上面的操作就是type=ALL,全表扫描.

3.2 INDEX 全表扫描,只是MYSQL扫描表时按索引次序而不是行.优点是避免了排序,缺点是要承担按索引顺序读取整个表的开销.

扫描时根据索引id的顺序扫描表,避免排序.

        如果extra中出现了"Using Index",说明Mysql使用了覆盖索引,它只扫描索引而不用回表,比按行扫描开销小很多,如下面的例子:

什么是覆盖索引? 就是说select的字段被索引完全覆盖,索引不需要回表去查其它的字段.如上面的例子:  id,act_id,publish_date这三个字段均被索引 "act_id-publish_date"覆盖,存储引擎不需要去查找聚簇索引来补充额外的其它查询字段.覆盖索引扫描是非常快的.


    3.3 range 

range 范围扫描是一个有限制的索引扫描,开始于索引的某一行.比全索引扫描好一些. 一般带有Between或者where 中有>的查询.另外 in() 和 or列表也显示范围扫描.


但是把上面的select * from xx where id>3 换成 "where act_id>3""就变成全表扫描了.


再看看in的例子,也显示范围扫描.



3.4 ref 

这是一种索引访问,它返回的是所有匹配某个单个值的行. 结果可能有多条数据,是"扫描和查找的混合体" 一般出现在非唯一索引或者唯一索引的某个前缀索引时才会发生.


上面是非唯一索引(learn_explain表中的second_index索引)的例子,如果是唯一索引的前缀索引呢?看下面的例子:


但如果我们用唯一索引来查找呢?如下所示:


type变成了 const .这是我们下面要说的type类型

     3.5, const,system  

查询分析器知道返回的只有一条数据.唯一索引和主键索引时会出现该类型.


     3.6, NULL  

在执行阶段不用再去访问表或者索引.

4, Possible_keys 

这一列显示查询可以使用哪些索引,但罗列出来的索引可能对后续优化过程没有用.


5, key

这一列显示MYSQL决定用哪个索引来对表进行访问. 如果该字段没出现在possible_keys中,那么mysql选用它是出于另外的原因-可能选择覆盖索引,那么没有where子句.
如下面的例子


6, key_len 列

该列显示了Mysql在索引里使用的字节数.


7, ref列

这一列显示之前在表的key列记录的索引中查找值所用的列或常量


8, rows列

这一列是mysql估计为了找到所需要的行而需要读取的行数.


9, extra列

9.1 using index

此值表示MYSQL将使用覆盖索引,已避免访问表.

9.2  using where

这意味着mysql服务器将在存储引擎检索后再进行过滤.

9.3 using temporary

这意味着mysql在对查询结果排序时会使用一个临时表.

9.4 using filesort 

这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行.

9.5 Range checked for each record

这个值意味着没有好用的索引,新的索引将在联接的每一行上重新估算.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值