一 建表和现象的过程如下

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 | | 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, 这是一个''表,表示子查询出现在FROM子句中,且本行的内容是一个类似“壳”一样的并无多大实质意义的‘虚表’,''中的数字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=5)) t;

-> ;

+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+

| id | select_type | table      | type  | possible_keys | key    | key_len | ref  | rows | filtered | Extra      |

+----+-------------+------------+--------+---------------+---------+---------+-------+------+----------+-------------+

|  1 | PRIMARY    | | 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 '5' AS `id1`,'5' AS `a1`,NULL AS `b1` from dual |

+-------+------+-----------------------------------------------------------------------+

1 row in set (0.00 sec)

"标题三"中和"标题一"中的SQL差别在于嵌套的子查询的形式是等号还是IN。

而IN的形式,被MySQL识别优化了标识子查询未“DERIVED ”了,这是MySQL从形式上目前只支持IN形式的子查询优化的优化,对于等号这样的形式,不支持。但是,从等式性质上,最终对"标题一"中的SQL进行了优化。

--------------------------------------分割线 --------------------------------------

Ubuntu 14.04 LTS 安装 LNMP Nginx\PHP5 (PHP-FPM)\MySQL http://www.linuxidc.com/Linux/2014-05/102351.htm

--------------------------------------分割线 --------------------------------------

mysql 执行计划不对_MySQL执行计划显示与执行过程不符合相关推荐

  1. mysql 执行计划不对_mysql tokudb执行计划走的不准确案例

    一.环境介绍 mysql版本:5.5.41-tokudb-7.5.5 表相关字段: `jlbh` varchar(31) NOT NULL, `hpys` varchar(1) NOT NULL, ` ...

  2. mysql执行计划性能_MySQL SQL性能分析Explain执行计划

    一. 执行计划返回信息详解 ①. 执行计划所含字段 输出列含义id查询标识 select_type查询类型 table查询涉及的表 partitions匹配到的分区信息 type连接类型 possib ...

  3. mysql 并发数 任务调度_mysql的计划任务与事件调度实例分析

    mysql的计划任务与事件调度实例分析 发布时间:2020-08-22 17:46:02 来源:脚本之家 阅读:98 作者:luyaran 本文实例讲述了mysql的计划任务与事件调度.分享给大家供大 ...

  4. mysql可以运行计时_mysql的event schedule 计时执行

    mysql的event schedule 可以让你设置你的mysql数据库再某段时间执行你想要的动作 这与视图是不相同的. create event test1 on schedule every 1 ...

  5. mysql 默认密码不对_mysql初始化密码常见报错问题

    1,mysql5.6是密码为空直接进入数据库的,但是mysql5.7就需要初始密码 cat /var/log/mysqld.log | grep password 1 2,然后执行 mysql -ur ...

  6. 查看mysql数据库的主机_MySQL查看或显示数据库(SHOW DATABASES语句)

    数据库可以看作是一个专门存储数据对象的容器,每一个数据库都有唯一的名称,并且数据库的名称都是有实际意义的,这样就可以清晰的看出每个数据库用来存放什么数据.在 MySQL 数据库中存在系统数据库和自定义 ...

  7. cmd命令行mysql乱码解决方法_mysql命令行显示乱码的解决方法

    mysql命令行显示乱码的解决方法:1.打开my.ini配置文件:2.修改配置[default-character-set=utf8]:3.改变数据库的编码方式,如[set character_set ...

  8. mysql中查询出生日期_MySQL查询以获取显示学生的出生日期的记录范围之间的日期?...

    要在日期之间获取记录,请使用BETWEEN.让我们首先创建一个表-mysql> create table DemoTable863(StudentDateOfBirth date); 使用插入命 ...

  9. mysql端口号不对_mysql 更改端口号踩的坑

    windows系统的配置文件在C:\ProgramData\MySQL\MySQL Server 5.7下的my.ini,怎么修改应该大家都知道,mysqld节点下的port更改为你想要的端口即可. ...

最新文章

  1. 如何使用 Cockpit 管理你的树莓派
  2. 【bzoj 4764】弹飞大爷
  3. string和C语言字符串之间的相互转换以及string常用函数
  4. 【机器学习】快速入门简单线性回归 (SLR)
  5. SQL基础E-R图画法(二)
  6. 字符编码笔记:ASCII,Unicode和UTF-8(转)
  7. Adobe出现正版验证提示如何解决?Adobe正版校验关闭教程
  8. python css selector_使用python处理selenium中的css_selector定位元素的模糊匹配问题
  9. python wget_python wget下载文件
  10. jquery weui 上拉加载,下拉刷新,问题解答。
  11. Go Playground exercise
  12. Bsphp验证系统,免费网络验证系统
  13. TI-C6657开发板烧录步骤
  14. html title中加图标,科技常识:HTML中title前面小图标的实现_如何给网页标题添加icon小图标...
  15. 原来苹果手机是这样清理内存的,能腾出大量内存,难怪用这么久还流畅
  16. 使用nginx搭建音视频点播服务——基于DASH协议
  17. php 网页爬虫 cooking,scrapy爬取dmoz/Home
  18. 运放单电源与双电源问题探讨
  19. 每日新闻 | 2018年全球十大IaaS服务商:中国占四席 阿里云第三
  20. python课后题答案董付国_python习题01——董付国学习系列

热门文章

  1. 光刻机的“崛起秘密”,第一本ASML的企业成长传记来了!
  2. 2021 年押宝哪个后端语言呢?
  3. 47 张图带你 MySQL 进阶
  4. JavaScript 你必须了解的主流趋势!
  5. C、C++ 不得宠,微软正开发新的编程语言!
  6. 被罚 50 亿后,Google 不再强制绑定 Android 默认引擎!
  7. React 是如何成为跨越前端开发鸿沟的桥梁?
  8. C++ 开发者怒了:这个无用的模块设计最终会害死 C++!
  9. @贾跃亭,证监会喊你本周回国对乐视负责!
  10. matlab怎么没有编辑器,实时编辑器介绍 - MATLAB Simulink - MathWorks 中国