MySQL执行计划--show warnings

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 以一个稍微复杂点的sql语句为例,使用show warnings命令查看MySQL执行计划的附加信息


     MySQL的的执行计划解释命令explain有个extended选项,这个选项在MySQL早期的版本中会产生额外的信息,这些额外的信息在explain的输入中不会显示,需要在运行explain之后使用show warnings命令查看。在5.7以上版本中,extended已经成为explain的默认选项,这也是每次执行explain命令后,总显示有一条告警的原因,extended命令选项虽然还能用,已经没有什么实际意义,纯粹是为了兼容以前的版本,在后面的版本中可能会被取消。

1 sql语句

     要解析的sql语句看起来稍微复杂一点,这样写的目的是尽可能的展示MySQL执行计划的不同内容,查询的是sakila数据库中管理员id为2 的仓库在所有国家用户的id,地址id,first_name,lastname,连接了sakila数据库的customer,addres,city三个表,对city的查询加了子查询,这里有意增加了复杂度,对子查询使用了联合,联合的是不是“Yemen”的国家和不是"Vietnam"的国家,联合起来就是所有的国家。对customer查询则简单使用了子查询 。

mysql> explain select  a.customer_id, a.address_id, a.first_name, a.last_namefrom customer a inner join  address b on a.address_id=b.address_id                inner join city c on b.city_id=c.city_idwhere  c.country_idin(select country_id from country where country<>"Yemen"unionselect country_id from country where country<>"Vietnam")and a.store_idnotin(select store_id from store where manager_staff_id=2);

2 语句的执行计划


+----+--------------------+------------+--------+--------------------+---------------------+-----------------+| id | select_type        |table| type   | key                | ref                 | Extra           |+----+--------------------+------------+--------+--------------------+---------------------+-----------------+|1| PRIMARY            | a          | ALL    |NULL|NULL| Using where||1| PRIMARY            | b          | eq_ref | PRIMARY            | sakila.a.address_id|NULL||1| PRIMARY            | c          | eq_ref | PRIMARY            | sakila.b.city_id| Using where||4| SUBQUERY           | store      | const  | idx_unique_manager | const               | Using index     ||2| DEPENDENT SUBQUERY | country    | eq_ref | PRIMARY            | func                | Using where||3| DEPENDENT UNION| country    | eq_ref | PRIMARY            | func                | Using where||NULL|UNION RESULT     |<union2,3>| ALL    |NULL|NULL| Using temporary |+----+--------------------+------------+--------+--------------------+---------------------+-----------------+

     select_type为PRIMARY的查询是最外层的查询,如果是子查询的时候,最外层的查询的类型是PRIMARY,外连接内连接最左边的查询其类型依旧是simple,从下面这个简单的例子可以看出来。

mysql> explain select a.city,b.countryfrom city a left join country b on a.country_id=b.country_id;+----+-------------+-------+--------+---------+---------------------+------+-------+| id | select_type |table| type   | key     | ref                 | rows | Extra |+----+-------------+-------+--------+---------+---------------------+------+-------+|1| SIMPLE      | a     | ALL    |NULL|NULL|600|NULL||1| SIMPLE      | b     | eq_ref | PRIMARY | sakila.a.country_id|1|NULL|+----+-------------+-------+--------+---------+---------------------+------+-------+2 rows inset,1 warning (0.00 sec)

       DEPENDENT SUBQUERY和DEPENDENT UNION的执行依赖外层查询执行的结果,在实际的sql编写中是应该尽可能避免的。

3 show warnings

      show warnings只对select语句有效,对update、delete和insert是无效的,命令显示的是在select语句中优化器是怎样标准化表名和列名,这里显示的sql语句是经过重写和应用优化规则后看起来的样子,还有关于优化器过程的其它信息。

      show warnings的输出里面有很多特殊的标记,这给阅读和理解造成了不小的麻烦,输入的格式也不是很友好,可读性较差,下面显示的输出是经过格式化了,读起来更容易一点。


mysql> show warnings\G;***************************1. row ***************************              Level: Note
               Code:1003            Message:/* select#1 */select `sakila`.`a`.`customer_id` AS `customer_id`,                                           `sakila`.`a`.`address_id` AS `address_id`,                                           `sakila`.`a`.`first_name` AS `first_name`,`sakila`.`a`.`last_name` AS `last_name` 
from `sakila`.`customer` `a` join `sakila`.`address` `b` join `sakila`.`city` `c`
where((`sakila`.`b`.`address_id` = `sakila`.`a`.`address_id`)and(`sakila`.`c`.`city_id` = `sakila`.`b`.`city_id`)and<in_optimizer>(                                                         `sakila`.`c`.`country_id`,<exists>(/* select#2 */select1from `sakila`.`country` where((`sakila`.`country`.`country` <>'Yemen')and(<cache>(`sakila`.`c`.`country_id`)= `sakila`.`country`.`country_id`))union/* select#3 */select1from `sakila`.`country` where((`sakila`.`country`.`country` <>'Vietnam')and(<cache>(`sakila`.`c`.`country_id`)= `sakila`.`country`.`country_id`))))and(not(<in_optimizer>(`sakila`.`a`.`store_id`,`sakila`.`a`.`store_id` in(<materialize>(/* select#4 */select'2'from `sakila`.`store` where1),<primary_index_lookup>(`sakila`.`a`.`store_id` in<temporary table>on<auto_key>where((`sakila`.`a`.`store_id` = `materialized-subquery`.`store_id`))))))))1 row inset(0.00 sec)            ERROR:            No query specified

        show warnings的输出里面有很多特殊标记,其中几个常见的标记的含义如下面所示:

      <auto_key>是为临时表自动创建的键(索引),

      <cache>表达式被执行了一次,获得的值存储到了内存中以供后来使用。如果表达式的执行结果是多个值,可能会创建一个临时表,那么这里看到的是<temporary table> 。

      <exists> 子查询匹配被转换成exists匹配,子查询需要转换,然后可以和exists一起使用的。

      <in_optimizer>优化器对象,对用户来说没有意义。

      <materialize>使用了子查询物化

      <primary_index_lookup> 使用主键来查询符合的行。

      知道了上面几个特殊标记的含义,就可以对show warnings的结果做出解释来了。

      /* select#1 */对应与执行计划中id为1的操作,一共有三个操作,执行的顺序是按从上到下依次执行的,这是一个三表连接操作,连接的顺序是a,b,c .后面的where条件里先出现的是这三个表 连接的join键,后面的两个部分分别对应sql语句中的其它两个where条件,<in_optimizer>表示后面的对象是优化器对象,可以不用关注。

    第一个where条件的<exists>表明后面的子查询被优化器转换成了exist表达式,/* select#2 */和/* select#3 */分别对应执行计划中id为2和3的查询,id为2的是依赖子查询,id为3 的是依赖union,它们依赖外层的country表传来的country_id,首次访问country_id后,其值被缓存起来以供后续使用。

    第二个where条件中的子查询使用了物化优化,/* select#4 */对应执行计划中的id为4的操作,从<primary_index_lookup>可以看出这个查询使用主键查询物化的临时表的行,使用的主键是MySQL为物化临时表自动创建的<auto_key>。

     从show warnings的结果中把所有的特殊标记去掉,就是经过优化器改写和转换后的sql语句。可以看出,MySQL优化器把第一个子查询转换成了exists表达式,对第二个子查询进行了物化优化。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
SQL 关系型数据库 MySQL
MySQL视图、索引、备份与恢复、执行计划(三)
MySQL视图、索引、备份与恢复、执行计划(三)
62 0
|
10天前
|
缓存 关系型数据库 MySQL
MySQL执行计划选择策略:揭秘查询优化的艺术
【10月更文挑战第15天】 在数据库性能优化中,选择最优的执行计划是提升查询效率的关键。MySQL作为一个强大的关系型数据库管理系统,提供了复杂的查询优化器来生成执行计划。本文将深入探讨如何选择合适的执行计划,以及为什么某些计划更优。
26 2
|
10天前
|
缓存 关系型数据库 MySQL
MySQL执行计划深度解析:如何做出最优选择
【10月更文挑战第23天】 在数据库查询性能优化中,执行计划的选择至关重要。MySQL通过查询优化器来生成执行计划,但有时不同的执行计划会导致性能差异。理解如何选择合适的执行计划,以及为什么某些计划更优,对于数据库管理员和开发者来说是一项必备技能。
24 2
|
10天前
|
SQL 关系型数据库 MySQL
美团面试:Mysql如何选择最优 执行计划,为什么?
在40岁老架构师尼恩的读者交流群中,近期有小伙伴面试美团时遇到了关于MySQL执行计划的面试题:“MySQL如何选择最优执行计划,为什么?”由于缺乏系统化的准备,小伙伴未能给出满意的答案,面试失败。为此,尼恩为大家系统化地梳理了MySQL执行计划的相关知识,帮助大家提升技术水平,展示“技术肌肉”,让面试官“爱到不能自已”。相关内容已收录进《尼恩Java面试宝典PDF》V175版本,供大家参考学习。
|
2月前
|
SQL 存储 关系型数据库
深入 MySQL 的执行计划与性能优化
深入 MySQL 的执行计划与性能优化
37 0
|
5月前
|
SQL 关系型数据库 MySQL
【Mysql】 深入理解MySQL的执行计划
【Mysql】 深入理解MySQL的执行计划
239 4
|
5月前
|
SQL 关系型数据库 MySQL
MySQL数据库——索引(4)-SQL性能分析-profile详情、explain(profile查看指令,explain执行计划中各个字段的含义)
MySQL数据库——索引(4)-SQL性能分析-profile详情、explain(profile查看指令,explain执行计划中各个字段的含义)
62 2
|
6月前
|
SQL 算法 关系型数据库
从执行计划了解MySQL优化策略
从执行计划了解MySQL优化策略
81 0
从执行计划了解MySQL优化策略
|
6月前
|
关系型数据库 MySQL 数据库
mysq优化---mysql执行计划解释、优化查询、数据库结构、服务器
mysq优化---mysql执行计划解释、优化查询、数据库结构、服务器
|
6月前
|
存储 关系型数据库 MySQL
MySQL查询执行计划详解(EXPLAIN)
一、单表查询 访问方法/访问类型: • const:通过主键值或唯一二级索引与一个常熟进行等值查询(不包括NULL),只会生成一条记录 • ref:普通二级索引与一个常数进行等值比较,可能生成多条记录 • ref_or_null:ref的前提下可以加上or key is null • range:对应的扫描区间为若干个单点扫描区间或范围扫描区间(不包括负无穷到正无穷的范围) • index:扫描区间为全表,但是可以在二级索引中扫描(因为二级索引每条记录占用空间更小,所以需要读的页更少) • all:直接扫描全部的聚集索引记录