07-MySql 慢查询分析-执行计划篇
文章目录
- 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 慢查询分析-执行计划篇相关推荐
- MySQL慢查询与执行计划分析
MySQL慢查询与执行计划分析 慢查询分析 执行计划分析 表结构分析 慢查询分析 查看是否开启慢日志: show variables like 'slow_query_log%'; +-------- ...
- Mysql 慢查询 Sql执行计划 SQL每阶段的耗时
文章目录 前言 一.慢查询的相关参数 slow_query_log 是否开启了慢查询 开启慢查询 slow_query_log_file 指定慢查询日志的存储路径及文件 long_query_time ...
- MySQL优化——Explain分析执行计划详解
文章目录 前言 一. 查看SQL执行频率 二. 定位低效率执行SQL 三. explain分析执行计划 3.1 id 3.2 select_type 3.3 table 3.4 type 3.5 ke ...
- mysql 分析执行计划的效率_MySQL执行计划分析
大家好,我是anyux.本文介绍MySQL执行计划分析. 作用 通过explain或desc命令将优化器选择后的执行计划截取出来,便于管理和判断语句的执行效率 获取执行计划 desc SQL语句 ex ...
- 最全MySQL8.0实战教程 22 MySQL的优化 22.4 explain分析执行计划 22.4.1 基本使用
最全MySQL8.0实战教程 文章目录 最全MySQL8.0实战教程 22 MySQL的优化 22.4 explain分析执行计划 22.4.1 基本使用 [黑马程序员MySQL知识精讲+mysql实 ...
- MySQL索引管理及执行计划
MySQL索引管理及执行计划 第1章 索引介绍: 索引是对数据库表中一列或者多列 的值进行排序的一种结构,使用索引可以快速访问数据库表中的特定信息,如果想按特定职员的姓名来查找,则与他在表中搜索所有的 ...
- 理解图形化执行计划 -- 第3部分:分析执行计划
英文原文: http://www.sqlservercentral.com/articles/Execution+Plans/105810/ 对于SQL Server数据库管理员和开发来说,能够理解和 ...
- 查询sql执行计划_使用SQL执行计划进行查询性能调整
查询sql执行计划 In the previous articles of this series (see the index at bottom), we went through many as ...
- MySQL 的索引、执行计划、优化器算法
SQL处理流程 INDEX 索引 索引介绍 索引:是排序的快速查找的特殊数据结构,定义作为查找条件的字段上,又称为键key,索引通过存储引擎实现: 索引相当于一本书的目录,可以优化查询. 优点: 索引 ...
最新文章
- mysqldump远程备份mysql数据库方法
- 财务人员学python有用吗-一个来自35岁职场高管的忠告:Python为什么不得不学?...
- .NET Socket服务编程之-高效连接接入编
- [python学习] 模仿浏览器下载CSDN源文并实现PDF格式备份
- python学习笔记(四):函数
- python echo服务器_python常用框架 echo server 的测试
- 一段在SAP C4C里触发S4HANA outbound Delivery的ABSL代码
- python3 规则引擎_几个常见规则引擎的简单介绍和演示
- ssm中spring mvc找不到控制器,报错404
- springboot-添加拦截器
- Centos 7 下 Mysql 5.7 Galera Cluster 集群部署
- 一、在Linux下,Nginx初安装及简单配置
- Tensorflow笔记:神经网络优化
- IDEA中JDBC连接MYSQL数据库步骤超详细总结
- web案例-3D旋转魔方和太极
- 服务器硬盘噪音大怎么回事,东芝服务器硬盘响声大吗?
- [C语言入门可读]学习书籍;学习工具、网站;刷题网站推荐
- [iOS]苹果开发证书 一个证书多人开发 注意项
- qq空间进入游戏显示服务器拒绝,显示ptlogin2.qq.com,QQ空间打不开的快速解决办法...
- 关爱亚孤儿 我们在行动——九巨龙肥城市京欣学校走进聊城市东昌府区
热门文章
- Shell-AWK命令分割文件内容并写入新文件(合并文件)
- lunix系统调用与库函数
- 学计算机的短期目标,大学生短期目标规划.docx
- 完成A轮融资,倍思如何发力场景化为品牌创造广阔未来?
- c语言怎么返回前一个程序,c语言return返回到哪
- srv服务器作用,srv记录是什么?有哪些用处?
- 视觉SLAM —— 李群与李代数
- 【华为OD机试 2023 B卷 | 100分】 统计射击比赛成绩(C++ Java JavaScript )
- 曾经有一份真挚的爱情摆在俺的面前,。。。
- Outlook2016如何配置Exchange邮箱