本文涉及到的内容比较多,预计阅读时间:30min
0x00 写在前面
使用explain关键字,除了看一下sql的join type,extra也是我们重点关注的一个信息。extra主要告诉我们,mysql是如何解析的sql。extra中的信息大家可能也并不陌生,比如常见的Using filesort、Using temporary、Using index等。那这些信息具体代表什么意思,能给我们优化sql带来什么样的指导?还有哪些常见的extra信息?且听我慢慢道来...
如果对explain中的type不太了解的朋友,可以看我上一篇文章 史上最强 | Mysql EXPLAIN详解 - 聊聊Type
本文基于mysql 8.0.17
0x01 Backward index scan
The optimizer is able to use a descending index on an InnoDB table. Shown together with Using index.
解析
如果在sql中有order by xx desc, 优化器可以在InnoDB表上使用倒序索引。实际上,在mysql8.x,extra中并不会显示Backward index scan,而是Using index。
在mysql5.7中,会显示Using index; Using filesort。
举例
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY a_idx(a DESC, b ASC));
INSERT INTO t1 VALUES(1,1),(2,2),(3,3);
EXPLAIN SELECT * FROM t1 ORDER BY a DESC, b;
mysql 8.0:
mysql 5.7:
多说一句
- 由于涉及到数据的存储,目前只支持InnoDB
- Descending index 无法使用change buffer
- Descneding index不支持fulltext或spatial index, 选择desc关键字会报错
- GROUP BY不在隐式的保证顺序性,只有明确的指定asc/desc,才去确保顺序
- MySQL 8.0之前,不管是否指定索引建的排序方式,都会忽略创建索引时候指定的排序方式(语法上不会报错),最终都会创建为ASC方式的索引
0x02 Child of 'table' pushed join@1
This table is referenced as the child of table in a join that can be pushed down to the NDB kernel. Applies only in NDB Cluster, when pushed-down joins are enabled.
解析
这个表被引用为可以下推到NDB内核的连接中的表的子表。 只适用于MySQL NDB集群,当启用了下推连接时。
举例
存在于NDB Cluster,笔者公司没有类似的环境。有兴趣的朋友可以自己研究一下。关于NDB可以参考一下:
https://cloud.tencent.com/developer/article/1055592
0x03 const row not found
For a query such as SELECT ... FROM tbl_name, the table was empty.
解析
官方文档:如果对一个空表进行简单查询,extra就是const row not found。官方文档这个地方描述的并不准确。比如,新建一张表(空表)
CREATE TABLE `t1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
如下语句:
EXPLAIN select * from t1
执行计划:
如果将存储引擎由InnoDB变更为MyISAM,执行计划如下:
这文档,不靠谱的!不过还是从网上找到了一个例子。
举例
-- 创建表t1(有一条数据)
CREATE TABLE `t1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
INSERT INTO t1 VALUES(1, 'a')
-- 创建表t2(空表)
CREATE TABLE `t2` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
执行查询
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.id = t2.id;
执行计划如下:
参考资料
MySQL · 引擎特性 · 8.0 Descending Index
Problem with joining to an empty table