文章目录

  • MySql执行计划
    • 一、执行计划的作用
    • 二、使用方式
    • 三、含义分析
      • 3.1 id
      • 3.2 select_type
      • 3.3 table
      • 3.4 Type
      • 3.5 possible_keys
      • 3.6 keys
      • 3.7 key_len
      • 3.8 ref
      • 3.9 rows
      • 3.10 extra
    • 四、示例
      • 4.1 数据库
      • 4.2 示例一
      • 4.3 示例二
    • 五、参考
    • 六、附数据库信息

MySql执行计划

  • 使用EXPLAIN命令可以查看MySql优化器执行SQL的细节,便于分析查询语句或是表结构的性能瓶颈。

一、执行计划的作用

  • 查看表的读取顺序。在多表关联查询时,可以看到查询每一张表的顺序
  • 查看数据读取操作的操作类型。根据对应的操作类型我们可以知道数据库获取数据的方式,比如是扫描还是走索引。
  • 查看索引信息。可以看到MySql可能会用到的索引和实际使用的索引。
  • 查看扫描记录的数量。确定是否扫描了数据,扫描的数量是多少(判断是否索引覆盖)

二、使用方式

  • 语法:EXPLAIN sql语句。比如
EXPLAIN select * from t_salary;
  • 输出:
id select_type table Type possible_keys keys key_len ref rows Extra
1 SIMPLE t_book ALL PRIMARY 3 Using temporary; Using filesort
1 SIMPLE t_role ref bookId,gangsId bookId 8 dbtest.t_book.id 1
1 SIMPLE t_gangs ALL PRIMARY 4 Using where; Using join buffer (Block Nested Loop)

三、含义分析

  • 本小节的数据库数据描述在第四节有介绍

3.1 id

  • id列包含一系列用于描述select查询的序列号,表示查询中执行select子句或操作表的顺序。根据id下面的2个原则可以判断出它们的执行顺序。
原则1:id大的比id小的先执行
原则2:id一样的,从上到下依次执行

3.2 select_type

  • select_type表示查询类型,有下面几种值
select_type 值 含义
SIMPLE 简单的SELECT语句(不包括UNION操作或子查询操作)
PRIMARY 查询中最外层的SELECT(如两表做UNION或者存在子查询的外层的表操作为PRIMARY,内层的操作为UNION)
UNION UNION操作中,查询中处于内层的SELECT(内层的SELECT语句与外层的SELECT语句没有依赖关系)
DEPENDENT UNION UNION操作中,查询中处于内层的SELECT(内层的SELECT语句与外层的SELECT语句有依赖关系)
UNION RESULT UNION操作的结果,id值通常为NULL
SUBQUERY 子查询中首个SELECT(如果有多个子查询存在):
DEPENDENT SUBQUERY 子查询中首个SELECT,但依赖于外层的表(如果有多个子查询存在) 注意:会严重消耗性能
DERIVED 被驱动的SELECT子查询(子查询位于FROM子句)
MATERIALIZED 被物化的子查询

3.3 table

  • 表名或者表别名

3.4 Type

  • 不同的Type代表的含义不同,(有点类似于MongoDB执行计划里面的stage)。一般需要得保证查询达到range级别,最好能达到ref。
Type值 含义
system 表只有一行记录
const 索引一次找到
eq_ref 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描
ref 非唯一性索引扫描,返回匹配某个单独值的所有行
range 只检索给定范围的行,使用一个索引来选择行。(好的sql至少应该是range或者以上基本的type)
index 当查询的结果全为索引列的时候,虽然也是全部扫描,但是只查询的索引库,而没有去查询数据。(是全表扫描的一种,是扫描索引文件,不需要扫描数据文件)
ALL Full Table Scan,将遍历全表以找到匹配的行

3.5 possible_keys

  • possible_keys:可能使用的key。如果查询中若使用了覆盖索引,则该索引和查询的select字段重叠。

3.6 keys

  • 实际使用的索引。如果为NULL,表示没有使用索引

3.7 key_len

  • key_len表示索引使用的字节数,可通过该列计算查询中使用的索引的长度,在不损失精确性的情况下,长度越短越好。
  • key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。

3.8 ref

  • 显示索引的哪一列被使用了

3.9 rows

  • 根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数

3.10 extra

  • 包含不适合在其他列中显示但十分重要的额外信息。
含义
Using filesort mysql无法通过索引进行排序(此时成为文件排序),使用一个外部的排序索引
Using temporary 使用了临时表保存中间结果(mysql排序时使用临时表,常见于order by或者group by)
Using index 是否使用了索引
Using where 表示使用了where过滤
Using join buffer 使用了连接缓存
Impossible where where子句的值总是false

四、示例

  • 本节只对比较关键的几个字段做简单的示例

4.1 数据库

  • 数据库包含3张表。
表名称 数据描述
t_book 保存书本信息
t_gangs 保存帮派信息
t_role 保存人物信息
  • 人物通过2个外键和书本以及帮派表关联

4.2 示例一

  • sql
-- 查询和“令狐冲”在一个帮派的其他人
EXPLAIN SELECTt_role.name
FROMt_role
WHEREt_role.gangsId = (SELECTt_role.gangsIdFROMt_roleWHEREt_role. NAME = "令狐冲");
  • 结果看到会先执行id为2的子查询部分;外层是PRIMARY,内层是SUBQUERY;使用的表是t_role;主查询的Type是ref表示返回匹配指定值的行,
    子查询为ALL因为子查询是查找名字为令狐冲的记录,但是name没有索引,因此是扫描全表去找记录;子查询没有使用索引,主查询使用了gangsId,
    因为gangsId是外键有索引;row字段因为子查询是全表扫描,表中包含13条记录,主查询因为已经找到了“令狐冲”对应的gangsId,主查询根据
    gangsId这个索引就找到了3条目标数据;Extra表示主查询和子查询都使用了where过滤。

4.3 示例二

  • sql
-- 查询武力值比余沧海高的人
EXPLAIN SELECTt_role. NAME,t_role.power
FROMt_role
WHEREt_role.power > (SELECTt_role.powerFROMt_roleWHEREt_role. NAME = "余沧海");
  • 在name和powder上没有创建索引之前,执行计划是这样的。我们看到主查询和子查询都是ALL全表扫描,因此这个是不好的,我们前面提到至少都要是range级别,最好能达到ref。
    我们分析子查询条件是name,因此需要name的索引,主查询是需要name和power这两个字段,为了能够索引覆盖,我们在name和power建立联合索引,在查询。

  • 在name和powder上创建联合索引之后,执行计划是这样的。我们看到子查询Type是ref代表返回匹配某个单独值的所有行,直接只查询一条记录就找到了目标记录,
    主查询则是扫描索引,但是却扫描了13条记录,为什么呢?我们看到主查询使用的是name_power的联合索引,但是查询条件实际上是power > xx ,这样的话是貌似无法直接命中记录。
    这里我们可以回顾B+数的特点,索引非叶子节点保存了name+power字段,但是我们的条件不是name而且power,因而这是看起来是索引覆盖了,时间上扫描了整颗索引树。

  • 如果在上一步的基础之上,将select的t_role. NAME字段去掉,只查询power,那么就是下面的效果,我们看到主查询也是有了索引,因为主查询使用power这个索引去查数据,
    并且select的字段就是索引字段,做到了索引覆盖,只扫描了6条记录,是比较好的。

五、参考

  • [1] MySQL创建数据表并建立主外键关系
  • [2] mysql 查询优化 ~explain解读之select_type的解读
  • [3] MySQL_执行计划详细说明
  • [4] mysql的sql执行计划详解(非常有用)

六、附数据库信息

  • SQL建表语句
/*
Navicat MySQL Data TransferSource Server         : 192.168.31.147
Source Server Version : 50639
Source Host           : 192.168.31.147:3306
Source Database       : dbtestTarget Server Type    : MYSQL
Target Server Version : 50639
File Encoding         : 65001Date: 2019-06-19 16:29:28
*/SET FOREIGN_KEY_CHECKS=0;-- ----------------------------
-- Table structure for t_book
-- ----------------------------
DROP TABLE IF EXISTS `t_book`;
CREATE TABLE `t_book` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`name` varchar(20) NOT NULL COMMENT '小说名称',`description` varchar(30) DEFAULT NULL COMMENT '小说描述',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='t_book 小说表';-- ----------------------------
-- Records of t_book
-- ----------------------------
INSERT INTO `t_book` VALUES ('1', '倚天屠龙记', '射雕三部曲之三');
INSERT INTO `t_book` VALUES ('2', '射雕英雄传', '射雕三部曲之一');
INSERT INTO `t_book` VALUES ('3', '神雕侠侣', '射雕三部曲之二');
INSERT INTO `t_book` VALUES ('4', '笑傲江湖', '家喻户晓的武侠');
INSERT INTO `t_book` VALUES ('5', '天龙八部', '最好的武侠之一');-- ----------------------------
-- Table structure for t_gangs
-- ----------------------------
DROP TABLE IF EXISTS `t_gangs`;
CREATE TABLE `t_gangs` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`name` varchar(20) NOT NULL,`detail` varchar(20) DEFAULT NULL COMMENT '帮派描述',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='t_gangs 帮派表';-- ----------------------------
-- Records of t_gangs
-- ----------------------------
INSERT INTO `t_gangs` VALUES ('1', '武当派', '位于武当山');
INSERT INTO `t_gangs` VALUES ('2', '少林派', '少室山');
INSERT INTO `t_gangs` VALUES ('3', '峨眉派', '峨眉山');
INSERT INTO `t_gangs` VALUES ('4', '全真教', '活死人墓对面');
INSERT INTO `t_gangs` VALUES ('5', '华山派', '位于华山');
INSERT INTO `t_gangs` VALUES ('6', '青城派', '四川青城山');
INSERT INTO `t_gangs` VALUES ('7', '嵩山派', '五岳剑派之首');
INSERT INTO `t_gangs` VALUES ('8', '丐帮', '天下第一大帮');
INSERT INTO `t_gangs` VALUES ('9', '大理段氏', '云南大理');-- ----------------------------
-- Table structure for t_role
-- ----------------------------
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`name` varchar(10) NOT NULL COMMENT '姓名',`age` int(3) DEFAULT '0' COMMENT '年龄',`power` int(3) DEFAULT '0' COMMENT '武力',`spirit` int(3) DEFAULT '0' COMMENT '精神',`bookId` bigint(20) NOT NULL COMMENT '关联的书本id',`gangsId` bigint(20) NOT NULL COMMENT '关联的帮派id',PRIMARY KEY (`id`),KEY `bookId` (`bookId`),KEY `gangsId` (`gangsId`),KEY `name_power` (`name`,`power`),KEY `power` (`power`),CONSTRAINT `t_role_ibfk_1` FOREIGN KEY (`bookId`) REFERENCES `t_book` (`id`),CONSTRAINT `t_role_ibfk_2` FOREIGN KEY (`gangsId`) REFERENCES `t_gangs` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='t_role 角色表';-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES ('1', '张无忌', '20', '98', '90', '1', '1');
INSERT INTO `t_role` VALUES ('2', '张三丰', '110', '99', '95', '1', '1');
INSERT INTO `t_role` VALUES ('3', '成昆', '50', '88', '90', '1', '2');
INSERT INTO `t_role` VALUES ('4', '灭绝师太', '48', '85', '90', '1', '3');
INSERT INTO `t_role` VALUES ('5', '王重阳', '55', '97', '95', '2', '4');
INSERT INTO `t_role` VALUES ('6', '尹志平', '44', '78', '75', '3', '4');
INSERT INTO `t_role` VALUES ('7', '令狐冲', '23', '92', '90', '4', '5');
INSERT INTO `t_role` VALUES ('8', '风清扬', '90', '98', '95', '4', '5');
INSERT INTO `t_role` VALUES ('9', '余沧海', '46', '82', '80', '4', '6');
INSERT INTO `t_role` VALUES ('10', '岳不群', '48', '86', '88', '4', '5');
INSERT INTO `t_role` VALUES ('11', '左冷禅', '50', '91', '88', '4', '7');
INSERT INTO `t_role` VALUES ('12', '乔峰', '30', '93', '90', '5', '8');
INSERT INTO `t_role` VALUES ('13', '段誉', '20', '94', '88', '5', '9');-- ----------------------------
-- Procedure structure for testtt_insert
-- ----------------------------
DROP PROCEDURE IF EXISTS `testtt_insert`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `testtt_insert`()
BEGIN
DECLARE i INT DEFAULT 1;
while i<10000
doinsert into t_test(name,description) values(concat('name',i),CONCAT('description',i)); set i = i+1;
end while;
commit;
end
;;
DELIMITER ;

07-MySql 慢查询分析-执行计划篇相关推荐

  1. MySQL慢查询与执行计划分析

    MySQL慢查询与执行计划分析 慢查询分析 执行计划分析 表结构分析 慢查询分析 查看是否开启慢日志: show variables like 'slow_query_log%'; +-------- ...

  2. Mysql 慢查询 Sql执行计划 SQL每阶段的耗时

    文章目录 前言 一.慢查询的相关参数 slow_query_log 是否开启了慢查询 开启慢查询 slow_query_log_file 指定慢查询日志的存储路径及文件 long_query_time ...

  3. MySQL优化——Explain分析执行计划详解

    文章目录 前言 一. 查看SQL执行频率 二. 定位低效率执行SQL 三. explain分析执行计划 3.1 id 3.2 select_type 3.3 table 3.4 type 3.5 ke ...

  4. mysql 分析执行计划的效率_MySQL执行计划分析

    大家好,我是anyux.本文介绍MySQL执行计划分析. 作用 通过explain或desc命令将优化器选择后的执行计划截取出来,便于管理和判断语句的执行效率 获取执行计划 desc SQL语句 ex ...

  5. 最全MySQL8.0实战教程 22 MySQL的优化 22.4 explain分析执行计划 22.4.1 基本使用

    最全MySQL8.0实战教程 文章目录 最全MySQL8.0实战教程 22 MySQL的优化 22.4 explain分析执行计划 22.4.1 基本使用 [黑马程序员MySQL知识精讲+mysql实 ...

  6. MySQL索引管理及执行计划

    MySQL索引管理及执行计划 第1章 索引介绍: 索引是对数据库表中一列或者多列 的值进行排序的一种结构,使用索引可以快速访问数据库表中的特定信息,如果想按特定职员的姓名来查找,则与他在表中搜索所有的 ...

  7. 理解图形化执行计划 -- 第3部分:分析执行计划

    英文原文: http://www.sqlservercentral.com/articles/Execution+Plans/105810/ 对于SQL Server数据库管理员和开发来说,能够理解和 ...

  8. 查询sql执行计划_使用SQL执行计划进行查询性能调整

    查询sql执行计划 In the previous articles of this series (see the index at bottom), we went through many as ...

  9. MySQL 的索引、执行计划、优化器算法

    SQL处理流程 INDEX 索引 索引介绍 索引:是排序的快速查找的特殊数据结构,定义作为查找条件的字段上,又称为键key,索引通过存储引擎实现: 索引相当于一本书的目录,可以优化查询. 优点: 索引 ...

最新文章

  1. mysqldump远程备份mysql数据库方法
  2. 财务人员学python有用吗-一个来自35岁职场高管的忠告:Python为什么不得不学?...
  3. .NET Socket服务编程之-高效连接接入编
  4. [python学习] 模仿浏览器下载CSDN源文并实现PDF格式备份
  5. python学习笔记(四):函数
  6. python echo服务器_python常用框架 echo server 的测试
  7. 一段在SAP C4C里触发S4HANA outbound Delivery的ABSL代码
  8. python3 规则引擎_几个常见规则引擎的简单介绍和演示
  9. ssm中spring mvc找不到控制器,报错404
  10. springboot-添加拦截器
  11. Centos 7 下 Mysql 5.7 Galera Cluster 集群部署
  12. 一、在Linux下,Nginx初安装及简单配置
  13. Tensorflow笔记:神经网络优化
  14. IDEA中JDBC连接MYSQL数据库步骤超详细总结
  15. web案例-3D旋转魔方和太极
  16. 服务器硬盘噪音大怎么回事,东芝服务器硬盘响声大吗?
  17. [C语言入门可读]学习书籍;学习工具、网站;刷题网站推荐
  18. [iOS]苹果开发证书 一个证书多人开发 注意项
  19. qq空间进入游戏显示服务器拒绝,显示ptlogin2.qq.com,QQ空间打不开的快速解决办法...
  20. 关爱亚孤儿 我们在行动——九巨龙肥城市京欣学校走进聊城市东昌府区

热门文章

  1. Shell-AWK命令分割文件内容并写入新文件(合并文件)
  2. lunix系统调用与库函数
  3. 学计算机的短期目标,大学生短期目标规划.docx
  4. 完成A轮融资,倍思如何发力场景化为品牌创造广阔未来?
  5. c语言怎么返回前一个程序,c语言return返回到哪
  6. srv服务器作用,srv记录是什么?有哪些用处?
  7. 视觉SLAM —— 李群与李代数
  8. 【华为OD机试 2023 B卷 | 100分】 统计射击比赛成绩(C++ Java JavaScript )
  9. 曾经有一份真挚的爱情摆在俺的面前,。。。
  10. Outlook2016如何配置Exchange邮箱