Explain:你见过这样的Sql吗?

上一篇我们讲到Mysql索引底层逻辑,为了了解后续sql知识,我们还是需要先学习一下相关“工具”得使用
一、Explain介绍EXPLAIN是MySQl必不可少的一个分析工具,主要用来测试sql语句的性能及对sql语句的优化,或者说模拟优化器执行SQL语句 。在select语句之前增加explain关键字,执行后MySQL就会返回执行计划的信息,而不是执行sql 。
注意:如果from中包含子查询,仍会执行子查询 , 将结果放入到临时表中
Explain的用法还是很简单的 , 类似一个关键字,无需记住什么语法相关的东西 , 我们主要来看他的输出,接下来我们看一下他的常见输出并分情况进行讨论:
首先我们创建三张表并插入一些相关数据
-- ------------------------------ Table structure for user-- ----------------------------DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (`id` int(11) NOT NULL,`name` varchar(45) DEFAULT NULL,`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,`create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;-- ------------------------------ Records of user-- ----------------------------INSERT INTO `user` VALUES ('1', '小明', '2022-09-15 15:52:18', '2022-09-13 15:52:21');INSERT INTO `user` VALUES ('2', '小红', '2022-09-14 15:52:35', '2022-09-06 15:52:41');INSERT INTO `user` VALUES ('3', '小可', '2022-09-15 15:52:55', '2022-09-15 15:52:58');INSERT INTO `user` VALUES ('4', '张三', '2022-09-13 15:53:13', '2022-09-14 15:53:17');INSERT INTO `user` VALUES ('5', '李四', '2022-09-15 15:53:35', '2022-09-15 15:53:37');INSERT INTO `user` VALUES ('6', '王五', '2022-09-15 15:53:47', '2022-09-15 15:53:49');INSERT INTO `user` VALUES ('7', '小小', '2022-09-15 15:54:06', '2022-09-15 15:54:08');-- ------------------------------ Table structure for address-- ----------------------------DROP TABLE IF EXISTS `address`;CREATE TABLE `address` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(45) DEFAULT NULL,PRIMARY KEY (`id`),KEY `idx_name` (`name`)) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;-- ------------------------------ Records of address-- ----------------------------INSERT INTO `address` VALUES ('2', '上海');INSERT INTO `address` VALUES ('1', '北京');INSERT INTO `address` VALUES ('3', '北京');INSERT INTO `address` VALUES ('5', '南京');INSERT INTO `address` VALUES ('6', '武汉');INSERT INTO `address` VALUES ('4', '深圳');INSERT INTO `address` VALUES ('7', '长沙');-- ------------------------------ Table structure for user_address-- ----------------------------DROP TABLE IF EXISTS `user_address`;CREATE TABLE `user_address` (`id` int(11) NOT NULL,`address_id` int(11) NOT NULL,`user_id` int(11) NOT NULL,`remark` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`),KEY `idx_user_address_id` (`address_id`,`user_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;首先来分析一下我们的表结构user表我们只有一个聚集索引,其实就是主键索引,那他的索引结构就只是id列 , 如下图所示:

Explain:你见过这样的Sql吗?

文章插图

Explain:你见过这样的Sql吗?

文章插图
address表不单单只有我们的聚集索引,也添加了一个二级索引 , 索引结构如下图所示:
Explain:你见过这样的Sql吗?

文章插图

Explain:你见过这样的Sql吗?

文章插图

Explain:你见过这样的Sql吗?

文章插图
user_address也不仅只有聚集索引,也有一个联合索引,相对应的列分别是address_id和user_id,索引结构如下图所示:
Explain:你见过这样的Sql吗?

文章插图

Explain:你见过这样的Sql吗?

文章插图

Explain:你见过这样的Sql吗?

文章插图
二、Explain中的列1、id列id列的编号是select的序列号,有几个select就有几个id,并且id的顺序是按select出现的顺序增长的 。
id列越大执行优先级越高,id相同则从上向下执行 , id为null最后执行 。
2、select_type列2.1、Simple:简单查询,查询不包含子查询和union
EXPLAIN SELECT * from `user` WHERE id = 1;
Explain:你见过这样的Sql吗?

文章插图
2.2、Primary:复杂查询中最外层的select
2.3、Subquery:包含在select中的子查询(不在from子句中)
2.4、Derived:包含在from子句中的子查询 。Mysql会将结果存放到一个临时表中 , 也成为派生表(derived的英文含义)
EXPLAIN SELECT (SELECT 1 FROM `user` WHERE id = 1) FROM (SELECT * FROM address WHERE id =1) der;

推荐阅读