MySQL的EXPLAIN其实很简单

EXPLAIN命令是查看查询优化器如何决定执行查询的主要方法,使用起来也非常简单,只需在SELECT(同样适用DELETE、UPDATE,本质还是SELECT)语句前加上EXPLAIN关键字即可,MySQL会返回关于在执行计划中的每一步的信息。

创建两个表用来测试验证下,product_category,product_info

CREATE TABLE `product_category` (
  `category_id` int(11) NOT NULL AUTO_INCREMENT,
  `category_name` varchar(64) CHARACTER SET utf8 NOT NULL,
  `category_type` int(11) NOT NULL
  PRIMARY KEY (`category_id`),
  UNIQUE KEY `uqe_category_type` (`category_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `product_info` (
  `product_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `product_name` varchar(64) NOT NULL,
  `product_price` decimal(8,2) NOT NULL,
  `product_stock` int(11) NOT NULL,
  `product_desc` varchar(64) DEFAULT NULL,
  `product_icon` varchar(512) DEFAULT NULL,
  `category_type` int(11) NOT NULL,
  PRIMARY KEY (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

先来看一个简单的示例:

explain select t.* from product_info t where t.product_id = 122;

返回如下信息:
在这里插入图片描述
1 id列
MySQL的查询可以分为简单类型和复杂类型,复杂类型又分为简单子查询,派生表(FROM子句中的子查询),UNION查询。如果只是一个简单查询,那id就会显示1,如果包含子查询,id会顺序编号。通常子查询中,id值大的优先执行。id相同的由上至下执行。

注意id值要结合具体sql语句,不能只看大小,例如:

explain select t.*,(select c.category_name from product_category c where c.category_type = t.category_type) from product_info t where t.product_id = 122;

结果如下:
在这里插入图片描述
子查询是DEPENDENT SUBQUERY,要依赖于主查询,所以执行顺序还是先执行id为1的查询,然后再执行id为2的查询。

2 select type列
此列展示了对应的row是简单查询还是复杂查询,常见的取值包含:
SIMPLE:不包含子查询和UNION
PRIMARY:外层查询
SUBQUERY:子查询
DEPENDENT SUBQUERY :依赖于外层查询的子查询
DERIVED:派生表查询

3 type列
(table和partitions表明正在访问的表和表分区,略过吧),type是访问类型,表明MySQL决定如何查找表中的行。取值包含如下(性能由差到好):
all:最差的全表扫描
index:a.跟全表一样,只是扫描时按索引次序进行而不是行,主要优点是避免了排序,但全表扫描依旧开销很大。b.如果在Extra出现"Using index"时,说明正在使用覆盖索引,只扫描索引的数据,开销相对全字段小很多。

比较两个简单的示例:

explain select t.product_name from product_info t order by t.product_id;

在这里插入图片描述
type是index,还是全表扫描。

explain select t.product_id from product_info t;

在这里插入图片描述
type是index,Extra是"Using index",只需扫描索引数据。

range:范围扫描,只检索给定范围内的行,当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN、LIKE或IN()运算符将字段列与常量进行比较时,可以使用Range。
例如:

explain select t.product_id from product_info t where t.product_id between 1000 and 2000;

在这里插入图片描述
ref:REF可用于使用=或<=>运算符进行比较的索引列,可以简单理解为使用了非主键、非唯一的索引。
例如,某个经常出现在条件查询的字段需要填加索引,但这个列值并不唯一。

explain select * from product_category c where c.category_name = '电器3C'

在这里插入图片描述
eq_ref:可以简单理解为走主键索引或唯一索引查找目标行。

const:匹配单行,走主键索引或唯一索引,通常根据主键查询某条记录的详情就是const了。

system:只有一行记录的表,属于const的特例,略过吧。

4 rows和filtered列
rows是MySQL评估为了找到所需的行而要读取的行数,可能不是很精准,读取的行数当然越小越好了。filtered是用来评估根据查询条件过滤数据的百分比,最大是100,这个也是越小越好了。rows × filtered就是可能用到的行数了。

5 possible_keys列
这一列罗列出查询可以使用哪些索引,是在优化过程早起创建的,可能对于后续优化过程并无用处。

6 key列
key就是索引了,标识可以走哪一个索引可以最小化查询成本。

7 key_len列
此列显示了索引字段使用的字节数,标识索引字段最大可能的长度,并非实际长度。不过也差不多,毕竟数据表字段大小是按需设计的。显然字段过长的值并不适合用作索引。例如,把一些诸如个人简介、文章内容类的字段监理索引是不恰当的。

猜你喜欢

转载自blog.csdn.net/weixin_43275277/article/details/106883815