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 ...
随机推荐
- [TOP10]十大渗透测试演练系统
本文总结了目前网络上比较流行的渗透测试演练系统,这些系统里面都提供了一些实际的安全漏洞,排名不分先后,各位安全测试人员可以亲身实践如何利用这个漏洞,同时也可以学习到漏洞的相关知识. DVWA (Dam ...
- postgreSQL初步使用总结
一.安装 postgreSQL安装完成后会默认生成一个名为postgres的用户和一个名为postgres的数据库.可以使用自带的psql.exe工具来登录.其帮助信息如下 连接到本地的postgre ...
- 关于EOF和循环体的搭配使用。
在oj中,变成如果有EOF和循环体的话,可能网页输入一个东西之后会输入另一个不知道是什么鬼,所以会造成这种情况.可能在输入应该输入的值以后还有一个值一起输入了,导致这种事情的发生. 比较两个图片观察 ...
- int和char的相同和不同。
int和char在存储量上有不同而且在编程的时候,这样才是正确的,如果这样的话,这是一个区别. 第二:这个和上面的道理应该是差不多的.输出97 98. 总的来说,int和char都是一个定义量器的 ...
- 程序员是怎么炼成的---OC题集--练习答案与题目(2)
1.objective-c中有垃圾回收机制吗? 没有像java.C#一样的垃圾回收机制,但是有ARC自动引用计数器技术,根据对象的引用技术来判断对象是否还在使用,如果RC=0,则系统就会销毁对象,实 ...
- Nginx启动出错 error while loading shared libraries:
在centos5.7 32位上编译安照 nginx-1.1.16 出错 [root@localhost conf]# /usr/local/nginx/sbin/nginx/usr/local/ngi ...
- 《more effective c++》条款26 限制类对象的个数
问题: 如何限制类对象的个数?比如1个,10个等等. 方法(1): 将类的构造函数定义为private,那么就无法实例化这个类了.但是如何创建1个对象出来?方法有2种: 1.声明一个友元函数,那么在友 ...
- 【题解】【位操作】【Leetcode】Single Number II
Given an array of integers, every element appears three times except for one. Find that single one. ...
- js缓速运动
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- CoreOS Linux available in China
CoreOS Linux 竭诚服务中国用户 今天,我们宣布一个令人振奋的消息 - CoreOS Linux 开源版本正式向中国地区提供服务!国内的用户们现在可以使用安全.自动的 CoreOS Linu ...