暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

Mysql 执行计划 id执行顺序解读

原创 唐晓波 2023-02-18
3042

适用范围

介绍Mysql数据库中,sql执行计划里各个id部分的执行顺序。

概念描述

由于客户数据库推行国产化这一趋势,我最近也在看mysql的sql优化。优化大家都知道看懂sql执行计划对于优化的意义,然而我在学习中发现网上的一些说法是不准确的。例如,“id一样,按照顺序执行;id越大,执行的优先级就越高(如子查询)......”,于是这里结合自己最近的学习跟大家说说怎么看mysql的执行计划。

 

具体概念:

mysql执行计划中的id和select-type有关系,需要结合id值和被执行对象之间的关系,才能确定id的执行次序,分为如下情况:

1. 并列关系:如两个表之间做UNION操作,这两个对象是并列的关系,则id值小的先执行。id值相同,从上到下,依次执行。
2. 嵌套的关系:如存在子查询,首先启动的是id值小的,即对父对象先进行操作,在id值小的对象执行过程中,接着又启动了id值为大的子对象。
所以,最先执行完毕的是id值大者;最先执行的是id值小者。   
3. 如果嵌套关系中,有多个子查询,且子查询间的关系是并列的,则执行顺序按照id序号进行,id值小的先执行。  
4. 如果子查询在优化阶段被执行,则执行阶段不再执行,这中情况与id值表示的执行顺序没有关系。

 

相关知识普及:

id:  在⼀个⼤的查询语句中每个SELECT关键字都对应⼀个唯⼀的id

select-type:  SELECT关键字对应的查询的类型

如下图所示:

派生表:<derivedN>形式,N表示产生派生表的查询的queryId
合并表:<unionN1,N2>形式,N2,N2表示参与union的查询的queryId

测试验证

下面通过测试来逐一说明一下:

(1)SIMPLE 简单查询,不包含union或者子查询,不做过多解释了

(2)PRIMARY 最外层的查询(并列关系示例)

mysql> EXPLAIN SELECT
    ->   o.emp_no,
    ->   o.birth_date,
    ->   t.first_name 
    -> FROM
    ->   ( SELECT a.emp_no, a.first_name FROM employees a WHERE a.first_name like 'G%' 
    ->     UNION 
    ->     SELECT a.emp_no, a.first_name FROM employees a WHERE a.gender = 'M' ) t
    ->   LEFT JOIN employees o ON o.emp_no = t.emp_no;

注释:按照网上的说法执行顺序是 4->3->2->1->1,这里其实是错误的。首先 t 是子查询,id=2和id=3是UNION的上下部分是并列关系,而id=4 是合并表其实就是<union2,3>查询的临时表也就是结果集 t。id=2又是id=1的派生表<derived2>,所以正确的执行顺序应该是2->3->4->1->1。

 

如果是mysql 8.0以上版本,可以查看explan analyze的执行计划:

注释:这个基本很接近oracle的执行计划了,遵守最右最上原则看即可。

(3)UNION 前面案例中id=2,id=3的部分,不再重复说了。

(4) UNION RESULT 前面案例中id=4的部分,不再重复说了。

(5)DERIVED 派生表,前面案例中id=1的部分,不再重复说了。

(6)DEPENDENT UNION 在union中的第二个或者之后的查询,并且外部查询依赖于union的结果(嵌套关系示例)

mysql> EXPLAIN SELECT
    ->  *
    -> FROM employees 
    -> WHERE
    ->   emp_no IN 
    ->   ( SELECT a.emp_no FROM employees a WHERE a.first_name like 'G%' 
    ->     UNION 
    ->     SELECT a.emp_no FROM employees a WHERE a.gender = 'M' ); 

注释:这里id=2,3,4的部分和前面类似,注意id=2的地方是DEPENDENT SUBQUERY,说明外部查询的结果依赖于union的结果属于嵌套关系,那么执行顺序是 2->3->4->1。当然外层查询的employees 是驱动表,被驱动表是id=4 返回的union的结果。

看下explain analyze的结果:

(7)subquery 在select或者where列表中包含的子查询

mysql> EXPLAIN SELECT
    ->   * 
    -> FROM
    ->   salaries s
    -> where
    ->   s.salary > (SELECT avg( salary ) FROM salaries)
    -> ;

explain analyze:的执行计划

注释:通常 SUBQUERY 的子查询只被执行一次,从explain analyze 执行计划中的提示可知。

知识总结

mysql执行计划中id的执行顺序,需要结合id值和被执行对象之间的关系才能确定。

1. 并列关系:如两个表之间做UNION操作,则id值小的先执行。id值相同,从上到下,依次执行。
2. 嵌套关系:如存在子查询,首先启动的是id值小的,即对父对象先进行操作,在id值小的对象执行过程中,接着又启动了id值为大的子对象。所以,最先执行完毕的是id值大者;最先执行的是id值小者。

参考文档

https://blog.csdn.net/fly2nn/article/details/61924721

MySQL执行计划中,ID值表明执行次序

MySQL 是怎样运行的:从根儿上理解 MySQL

MySQL执行计划中,ID值表明执行次序

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论