MySQL执行计划显示与执行过程不符合一例
一 建表和现象的过程如下
CREATE TABLE t1 (id1 INT, a1 INT, b1 INT, PRIMARY KEY(id1));
CREATE TABLE t3 (id3 INT UNIQUE, a3 INT, b3 INT);
INSERT INTO t1 VALUES (1, 1, NULL);
INSERT INTO t3 VALUES (1, 1, NULL);
mysql> select * from (select * from t1 where id1 =(select id3 from t3 where id3=1)) t;
+-----+------+------+
| id1 | a1 | b1 |
+-----+------+------+
| 1 | 1 | NULL |
+-----+------+------+
1 row in set (0.01 sec)
mysql> explain extended select * from (select * from t1 where id1=(select id3 from t3 where id3=1)) t;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
| 2 | DERIVED | t1 | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
| 3 | SUBQUERY | t3 | const | id3 | id3 | 5 | const | 1 | 100.00 | Using index |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)
mysql> show warnings;
+-------+------+-----------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-----------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select '1' AS `id1`,'1' AS `a1`,NULL AS `b1` from dual |
+-------+------+-----------------------------------------------------------------------+
1 row in set (0.00 sec)
二 分析:
首先, 察看执行计划:
1 id值为1的select_type值为PRIMARY, 这是一个'<derived2>'表,表示子查询出现在FROM子句中,且本行的内容是一个类似“壳”一样的并无多大实质意义的‘虚表’,'<derived2>'中的数字2来自于下一行id为2的结果。而别名为t的子查询,确实出现在最外层的FROM中。
2 id值为2的select_type值为DERIVED,表示这是一个被驱动的表(被驱动的FROM子句中的子查询).
3 id值为3的select_type值为SUBQUERY,表示嵌套中的第二个在t3表上的子查询,没有被优化为其他类型(优化可如子查询被消除后转为内连接)。
其次,察看警告信息:
1 FROM子句后的表变为了‘dual’这一虚表,t1和t2全部消失。为什么?
2 MySQL在优化的过程中,利用等式的性质,推知了:
2.1 id1=id3=1
2.2 查询语句从逻辑推理上,就可以变形为:select * from t1 where id1=1
此时,子查询其实被消除了,但是执行计划中没有体现这一点,这是执行计划错误之处。
2.3 进一步,t1表上id1列是主键,所以根据索引,可以查知*对应的目标列的值:这样,逻辑推理上,就可以变形为:
select '1' AS `id1`,'1' AS `a1`,NULL AS `b1` from t1 where id1=1
2.4 因为目标列的值已经能够在优化的过程中得知,所以FROM子句中的表,可被标识为“常量表”。
3 于是,在显示查询执行计划的后期(explain命令后期),代码中有个判断:如果表全部是常量表且已经是“被优化了的(optimized_away)”则把FROM子句中的表对象,用“dual”替换。这就是警告中为什么会出现“from dual”的原因。
再次,执行计划和警告信息显示存在不一致,那么,MySQL在执行的时候,是按照谁来执行呢?
这点可以通过跟踪代码进行分析。
执行过程如下:
1 优化阶段:即生成执行计划阶段
MySQL在优化阶段的过程,就如执行计划显示的结果一样,对各个子句进行着执行计划显示的过程,先是因为FROM子句中的子查询执行id为1的过程,然后是对被驱动的id为2的优化,在没有结束id为2的优化的过程中,发现id为2的子句是子查询,就嵌套调用去优化子查询,于是引发了等式化简等过程。
在运用各种技术做各种化简的过程中,一些值或结果已经得知,顺带即完成了一些求解的工作。
这也说明一个问题:有的朋友问id间的序号表明了一个什么样的执行次序?因为嵌套的关系,首先启动的是id值小的,在id值为小的执行过程中,接着又启动了id值为大的查询子句,所以,最先执行完毕的,是id值大者;最先执行的,是id值小者。
2 执行阶段:
已经知道是一个常量求解,且结果在优化过程中得知,直接输出。
这也解释了警告信息中得到的是“from dual”,与执行过程的含义,相符。即:执行阶段,查询计划表明的过程已经结束了。
三 补充说明
mysql> explain extended select * from (select * from t1 where id1 in (select id3 from t3 where id3=1)) t;
-> ;
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
| 2 | DERIVED | t1 | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
| 2 | DERIVED | t3 | const | id3 | id3 | 5 | const | 1 | 100.00 | Using index |
+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+
3 rows in set, 1 warning (49.53 sec)
mysql> show warnings;
+-------+------+-----------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-----------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select '1' AS `id1`,'1' AS `a1`,NULL AS `b1` from dual |
+-------+------+-----------------------------------------------------------------------+
1 row in set (0.00 sec)
"标题三"中和"标题一"中的SQL差别在于嵌套的子查询的形式是等号还是IN。
而IN的形式,被MySQL识别优化了标识子查询未“DERIVED ”了,这是MySQL从形式上目前只支持IN形式的子查询优化的优化,对于等号这样的形式,不支持。但是,从等式性质上,最终对"标题一"中的SQL进行了优化。
参考:
http://blog.163.com/li_hx/blog/static/18399141320146219354154/
MySQL执行计划显示与执行过程不符合一例的更多相关文章
- ORACLE实际执行计划与预估执行计划不一致性能优化案例
在一台ORACLE服务器上做巡检时,使用下面SQL找出DISK_READ最高的TOP SQL分析时,分析过程中,有一条SQL语句的一些反常现象,让人觉得很奇怪: SELECT SQL_ID, ...
- xplan.sql(本脚本获取执行计划显示执行顺序)
-- ---------------------------------------------------------------------------------------------- -- ...
- MySQL执行计划解析
前言 在实际数据库项目开发中,由于我们不知道实际查询时数据库里发生了什么,也不知道数据库是如何扫描表.如何使用索引的,因此,我们能感知到的就只有SQL语句的执行时间.尤其在数据规模比较大的场景下,如何 ...
- MYSQL与TiDB的执行计划
前言 这里采用了tpc-h一个数据库的数据量来进行查询计划的对比.并借助tpc-h中的22条查询语句进行执行计划分析. mysql采用的是标准安装,TiDB采用的是单机测试版,这里的性能结果不能说明其 ...
- 读懂MySQL执行计划
原文:https://mp.weixin.qq.com/s/-BlLvBKcF-yalELY7XkqaQ 前言 在之前的面试过程中,问到执行计划,有很多童鞋不知道是什么?甚至将执行计划与执行时间认为是 ...
- MySQL执行计划分析
原文:MySQL执行计划分析 一. 执行计划能告诉我们什么? SQL如何使用索引 联接查询的执行顺序 查询扫描的数据函数 二. 执行计划中的内容 SQL执行计划的输出可能为多行,每一行代表对一个数据库 ...
- 高性能可扩展mysql 笔记(六) SQL执行计划及分页查询优化、分区键统计
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 常见业务处理 一.使用数据库处理常见业务: 案例: 如何对评论进行分页展示 使用 EXPLAIN 获得s ...
- mysql之优化器、执行计划、简单优化
mysql之优化器.执行计划.简单优化 2018-12-12 15:11 烟雨楼人 阅读(794) 评论(0) 编辑 收藏 引用连接: https://blog.csdn.net/DrDanger/a ...
- MySQL 查看执行计划
MySQL 使用 explain + sql 语句查看 执行计划,该执行计划不一定完全正确但是可以参考. EXPLAIN SELECT * FROM user WHERE nid = 3; selec ...
随机推荐
- Android Launcher 详解
(1) Launcher的定义:Android系统启动后,加载的第一个程序,是其他应用程序的入口. (2) Launcher的构成:HomeScreen(1.workspace(A ...
- Python OpenCV ——Matplotlib显示图片
Color image loaded by OpenCV is in BGR mode.But Matplotlib displays in RGB mode.So color images will ...
- 钱币兑换问题_完全背包&&拆分&&母函数
ps:原来用新浪,可是代码的排版不是很好,所以用博客园啦,先容许我把从八月份开始的代码搬过来,从这里重新出发,希望这里可以一直见证我的成长. Time Limit: 2000/1000 MS (Jav ...
- HDU 5862(离散化+树状数组)
Problem Counting Intersections 题目大意 给定n条水平或竖直的线段,统计所有线段的交点个数. (n<=100000) 解题分析 首先将线段离散化. 然后将所有线段按 ...
- MySQL 仅保留7天、一个月数据
/************************************************************************** * MySQL 仅保留7天.一个月数据 * 说明 ...
- CSS 实现:父元素包含子元素,子元素垂直居中布局
☊[实现要求]:父元素包含子元素,子元素垂直居中布局 <div class="demo5"> <div class="child">A& ...
- 【avalon】offsetParent
offsetParent: function () { var offsetParent = this[0].offsetParent while (offsetParent && a ...
- Azure 云助手正式发布
Azure云服务在中国市场风生水起,越来越多的用户选择Azure作为平台将业务转向云端.随着移动互联网在中国的蓬勃发展,手机应用的体验深入人们的生活及工作.用户管控云服务也不应该只局限于电脑前,而是可 ...
- 说说Audition消除歌曲中的人声
今天再说说消除人声,音乐中人声的消除有多种方法,但都很难完全消除,而且效果越好越难消除,一首音效极佳的立体声歌曲是无法完全消除人声的.本人常用的是以下三种方法.第1种如下图,此方法简单,但是完成后变成 ...
- Linux启动流程详解
在BIOS阶段,计算机的行为基本上被写死了,可以做的事情并不多:一般就是通电.BIOS.主引导记录.操作系统这四步.所以我们一般认为加载内核是linux启动流程的第一步. 第一步.加载内核 操作系统接 ...