前言

平时我们优化sql,通过explain,分析得到的执行计划研究透彻,知道每个执行计划在底层是如何执行的,那么再进行相关的调优就轻而易举了。所谓的执行计划,落实到底层,无非就是先访问哪个表,用哪个索引还是全表扫描,拿到数据之后如何去聚簇索引回表,是否要基于临时磁盘文件做分组聚合或者排等序等等

基本介绍

接下来我们分析一下执行计划里包含的各个字段都是什么意思

字段名 意义
id 每个select都会对应一个id,一个复杂的sql里有多个select,那么有可能出现多条执行计划
select_type 执行计划对应的查询是个什么查询类型
table 查询表名
type 当前表访问的方法 const(聚簇索引)、ref(二级索引)、range(范围索引)、index(扫描所有叶子节点)、all(全表扫描)
possible_keys 跟type结合起来,显示可提供的选择索引
key 实际选择的索引
key_len 索引的长度
ref 使用某个字段的索引进行等值匹配搜索,索引列进行等值匹配的那个目标值的一些信息
rows 大概可能会读取多少条数据
filtered 经过搜索条件过滤之后的剩余数据的百分比
extra 额外的信息

案例分析

最简单的查询我们先忽略掉

案例一

EXPLAIN SELECT * FROM A WHERE x2 = ‘xxxx’ or x1 IN (SELECT x1 FROM B);
可以看出,select语句的where条件包含了一个子查询和一个自己的筛选,执行计划如下

id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra
-------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | -----
1 | PRIMARY | A| NULL | ALL | index_x2 | NULL | NULL | NULL | 2177 | 100.00 | Using where
2 | SUBQUERY | B | NULL | index | index_x1 | index_x1 | 315 | NULL | 408 | 100.00 | Using index

我们发现他有两个两条执行计划,一条是PRIMARY,一条是SUBQUERY。
第一个执行计划的查询类型是主查询的意思,对主查询而言,他有一个where条件是x2=‘xxxx’,所以他的possible_keys里包含了index_x2,就是x2字段的索引,但是他的key实际是NULL,而且type是ALL,所以说他最后没选择用x2字段的索引,而是选择了全表扫描

第二条执行计划是子查询,子查询针对的是B这个表,当然子查询本身就是一个全表查询,但是对主查询而言,会使用x1 in 这个筛选条件,他这里type是index,说明使用了扫描index_x1这个x1字段的二级索引的方式,直接扫描x1字段的二级索引,来跟子查询的结果集做比对。

案例二

EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
-------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | -----
| 1 | PRIMARY | A| NULL | ALL | NULL | NULL | NULL | NULL | 5565 | 100.00 | NULL |
| 2 | UNION | B| NULL | ALL | NULL | NULL | NULL | NULL | 3523| 100.00 | NULL |
| NULL | UNION RESULT | <union1,2> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Using temporary |

前两条分别从A表和B表进行全表扫描,第三条的extra里是using temporary,使用临时表的意思,把结果集放到临时表里去重

案例三

EXPLAIN SELECT * FROM (SELECT x1, count(*) as num FROM A GROUP BY x1) AS B where num> 10

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
-------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | -----
| 1 | PRIMARY | derived2 | NULL | ALL | NULL | NULL | NULL | NULL | 3468 | 33.33 | Using where |
| 2 | DERIVED | A| NULL | index | index_x1 | index_x1 | 899 | NULL | 3568 | 100.00 | Using index |

第二条select_type是derived,是针对子查询执行后的结果集会物化为一个内部临时表。在进行分组聚合时,使用x1的索引进行,因为type是index,所以直接扫描这个索引树的所有叶子节点。
第二条select_type是primary,针对的table是derived2,是子查询结果集物化形成的临时表,直接针对这个物化临时表进行了全表扫描,根据where条件进行筛选的。

Extra

Using index

比如下面的SQL语句:

EXPLAIN SELECT x1 FROM t1 WHERE x1 = ‘xxx’,x1是二级索引

该次查询仅仅涉及到了一个二级索引,不需要回表

Using index condition

比如下面的SQL语句:

SELECT * FROM t1 WHERE x1 > ‘xxx’ AND x1 LIKE ‘%xxx’,x1是二级索引

先在二级索引index_x1里查找,查找出来的结果还会额外的跟x1 LIKE '%xxx’条件做比对,如果满足条件的才会被筛选出来,这种情况下,extra显示的是Using index condition。

Using where

没用到索引,然后where里好几个条件,就会告诉你Using where,或者是你用了索引去查找,但是除了索引之外,还需要用其他的字段进行筛选,也会告诉你Using where。综上,只要用了没有索引的字段去查找,都会展示Using where

Using filesort

在SQL语句里进行排序的时候,如果排序字段是有索引的,那么其实是直接可以从索引里按照排序顺序去查找数据的,比如这个SQL:

EXPLAIN SELECT * FROM t1 ORDER BY x1 LIMIT 10,x1是二级索引

extra 其实就是为null

但是如果我们排序的时候是没法用到索引的,此时就会基于内存或者磁盘文件来排序,大部分时候得都基于磁盘文件来排序,比如说这个SQL:

EXPLAIN SELECT * FROM t1 ORDER BY x2 LIMIT 10,x2没有索引

没法直接根据有序的索引去找数据的,只能把所有数据写入一个临时的磁盘文件,基于排序算法在磁盘文件里按照x2字段的值完成排序,Extra展示为Using filesort,性能极差

Using tempory

如果我们用group by、union、distinct之类的语法的时候,万一要是没法直接利用索引来进行分组聚合,那么会直接基于临时表来完成,也会有大量的磁盘操作,性能其实也是极低的。

比如这个SQL:
EXPLAIN SELECT x2, COUNT(*) AS amount FROM t1 GROUP BY x2,x2没有索引

Extra展示为Using tempory,性能极差

浅谈mysql的执行计划是何方神圣相关推荐

  1. oracle for循环_浅谈Oracle的执行计划

    执行计划执行计划是一条sql语句在ORACLE中的执行过程或访问路径的描述.即对一个sql语句,从执行计划可以看出oracle完成任务的详细方案.如果要分析某条SQL的性能问题,通常我们要先看SQL的 ...

  2. mysql维护计划任务_浅谈MySQL event 计划任务

    一.查看event是否开启 show variables like '%sche%'; set global event_scheduler =1; 二. -- 设置时区并设置计划事件调度器开启,也可 ...

  3. mysql 计划任务消耗_浅谈MySQL event 计划任务

    一.查看event是否开启 show variables like '%sche%'; set global event_scheduler =1; 二. -- 设置时区并设置计划事件调度器开启,也可 ...

  4. 浅谈 MySQL 子查询及其优化

    2019独角兽企业重金招聘Python工程师标准>>> 使用过oracle或者其他关系数据库的DBA或者开发人员都有这样的经验,在子查询上都认为数据库已经做过优化,能够很好的选择驱动 ...

  5. php 如何设计索引_Mysql学习浅谈mysql的索引设计原则以及常见索引的区别

    <Mysql学习浅谈mysql的索引设计原则以及常见索引的区别>要点: 本文介绍了Mysql学习浅谈mysql的索引设计原则以及常见索引的区别,希望对您有用.如果有疑问,可以联系我们. 索 ...

  6. MySQL子查询的优缺点_浅谈mysql的子查询

    浅谈mysql的子查询 mysql的子查询的优化一直不是很友好,一直有受业界批评比较多,也是我在sql优化中遇到过最多的问题之一,你可以点击这里 ,这里来获得一些信息,mysql在处理子查询的时候,会 ...

  7. 浅谈MySQL存储引擎-InnoDBMyISAM

    浅谈MySQL存储引擎-InnoDB&MyISAM 存储引擎在MySQL的逻辑架构中位于第三层,负责MySQL中的数据的存储和提取.MySQL存储引擎有很多,不同的存储引擎保存数据和索引的方式 ...

  8. mysql declare与set的区别_浅谈MySQL存储过程中declare和set定义变量的区别

    在存储过程中常看到declare定义的变量和@set定义的变量.简单的来说,declare定义的类似是局部变量,@set定义的类似全局变量. 1.declare定义的变量类似java类中的局部变量,仅 ...

  9. 浅谈代码的执行效率(4):汇编优化

    终于谈到这个话题了,首先声明我不是汇编优化的高手,甚至于我知道的所有关于汇编优化的内容,仅仅来自于学校的课程.书本及当年做过的一些简单练习.换句话说,我了解的东西只能算是一些原则,甚至也有一些&quo ...

最新文章

  1. ValueTransformer
  2. 前端JavaScripts基础知识点讲义代码
  3. 如何做PHD (1)
  4. MySQL 获取系统时间/系统日期/日期时间的函数
  5. 史上最全java架构师技能图谱(上)
  6. 数组元素在删减的同时进行遍历的操作,程序崩溃问题
  7. jenkins+docker 持续构建非docker in docker
  8. ABAQUS后处理常用功能
  9. 2016服务器系统驱动,windows sever2016驱动大家是怎么装的啊
  10. 2.4 PRINCE2
  11. Java 基础 - List 遍历时为什么不能通过 for 循环进行删除,而使用 Iterator 可以 ?
  12. “十三五”电力科技重大发展方向及关键技术
  13. xiaomi 小米6刷ubuntu touch
  14. mysql怎么优化like_MySQL 的 like %关键字怎么优化
  15. 特岗计算机考试题2018年,2020年特岗模拟考试试题及答案.pdf
  16. 华擎H97 Performance 1150主板板载千兆网卡手动从百兆切换千兆设置
  17. python对象方法 反射
  18. php 判断数组值为空,PHP判断数组是否为空的五种常用方法
  19. Matlab关键规则挖掘尿片啤酒,数据挖掘:“啤酒+尿布”的关联规则是怎么来的?...
  20. 基于java的超市积分管理系统

热门文章

  1. 关于字体绘制的baseline (QT 和 D2D)
  2. PS图层混合算法之五(饱和度,色相,颜色,亮度)
  3. 谈谈数独(Sudoku)
  4. 融合注意力机制和Bi-LSTM的旅游评价情感分析模型
  5. 【模拟·习题】[USACO18JAN]Lifeguards S
  6. ApacheCon Asia 2022 开启报名:Pulsar 技术议题重磅亮相
  7. 苹果内置录屏SDK-ReplayKit库的使用说明
  8. 南开大学计算机宁博,周亚训 教授
  9. GET请求里的body问题
  10. 云计算与大数据考试重点