前言

有时候,我们写好SQL后发现执行查询的时间超过了预期,但自己已经有根据表的已有索引去写SQL语句,这个时候就要考虑是否是在查询的过程中出现了索引失效的问题。那么我们可以怎么样去验证SQL在执行过程中是否有使用到索引呢?数据库给我们提供了explain关键字去查看sql的执行过程。

本篇文章将介绍explain关键字的用法和各个参数的含义,以期对该函数不了解的开发人员能够快速掌握SQL分析的技能。

本篇文章将以department和employee两张表(具体见后面的表结构参考)为例,进行文章的讲解,其中employee的name和age做了组合索引 。

语法

explain 要分析的SQL语句

image.png

以上图为例,当我们使用explain来分析select * from employee这条句子后发现,出现了id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra共十个字段。那么这些字段分别是什么意思呢?我们可以通过这些字段的值来判断当前索引是否失效呢?下面,将对上述问题一一进行解答。

(一)explain字段含义解析

1. id

id表示执行select子句或者操作表的顺序

id相同时,从上到下依次执行

id不同时,根据id从大到小依次执行。(如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行)

image.png

以上图为例,使用explain关键字查看sql执行过程后发现,会先执行id为2的子查询语句,再分别查询emp和dep两张表。至于为什么有这样的先后之分,是因为sql执行查询的时候会优先执行子查询语句的内容。

2. select_type

表示每个查询项的查询类型

类型

作用

SIMPLE

简单SELECT,不使用UNION或子查询等

PRIMARY

查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY

UNION

UNION中的第二个或后面的SELECT语句

DEPENDENT UNION

UNION中的第二个或后面的SELECT语句,取决于外面的查询

UNION RESULT

UNION中的第二个或后面的SELECT语句,取决于外面的查询

SUBQUERY

子查询中的第一个SELECT

DERIVED

派生表的SELECT, FROM子句的子查询

mysql> explain select * from department where id=(select id from employee where name='tony') union select * from department where id=(select id from employee where name='niky');

+------+---------------+-----------+-------+--------------+----------+---------+-------+-------+-------------+

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |

+------+---------------+-----------+-------+--------------+----------+---------+-------+-------+-------------+

| 1 | PRIMARY | department | const | PRIMARY | PRIMARY | 4 | const | 1 | |

| 2 | SUBQUERY | employee | ALL | NULL | NULL | NULL | NULL | 8 | Using where |

| 3 | UNION | department | const | PRIMARY | PRIMARY | 4 | const | 1 | |

| 4 | SUBQUERY | employee | ALL | NULL | NULL | NULL | NULL | 8 | Using where |

| NULL | UNION RESULT | | ALL | NULL | NULL | NULL | NULL | NULL | |

+------+---------------+-----------+-------+--------------+----------+---------+-------+-------+-------------+

5 rows in set (0.08 sec)

以上面的例子,我们基本上可以看出常见的几种查询类型是在什么情况下使用的。

3. table

显示这一行的数据是关于哪张表的,有时是真实的表名字,有时也可能是以下几种结果

: 指id为M,N行结果的并集

: 该行是指id值为n的行的派生表结果。派生表可能来自例如from子句中的子查询。

: 该行是指id值为n的行的物化子查询的结果。

4. type(重要参数)

连接使用了哪种类别,有无使用索引,常用的类型有:system, const, eq_ref, ref, range, index, ALL(从左到右,性能越来越差)

类型

说明

all(Full Table Scan)

没有用到索引,MySQL将遍历全表以找到匹配的行

index(Full Index Scan)

index与ALL区别为index类型只遍历索引树

range

只检索给定范围的行,使用一个索引来选择行

ref

表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

eq_ref

类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件

const

该表最多具有一个匹配行,该行在查询开始时读取。

system

该表只有一行(=系统表)。这是[const]联接类型的特例 。

一般来说,sql的级别能够达到eq_ref~index的话,都算是性能尚可的查询。

5. possible_keys

表示SQL能够使用哪些索引在表中查询数据,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用。也就是说,这个字段只是列出了可能使用到的索引,当出现理论上有使用索引,实际上没有的情况,很大可能就是出现了索引失效的问题了。

image.png

6. key(重要)

key列显示数据库实际决定使用的键(索引)

如果实际执行查询过程中,没有使用索引,此处的值为NULL。

使用的索引的长度。在不损失精确性的情况下,长度越短越好

image.png

7.ref

表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

这里要注意和type中的ref属性作区分,这里的ref是指作为匹配条件的值,而后者是指查询的一种类型。

image.png

如上图,ref对应的值为const,说明作为匹配条件的“niky”是一个常量。

8. rows

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

image.png

这里表示需要扫描读取8行数据

9.Extra(重要)

该列包含MySQL解决查询的详细信息,有以下几种情况

Using where

使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题

image.png

Uing index

列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候,表示mysql服务器将在存储引擎检索行后再进行过滤

image.png

Using join buffer

改值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。

Impossible where

这个值强调了where语句会导致没有符合条件的行。

image.png

Using temporary

表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询。

Using filesort

MySQL中无法利用索引完成的排序操作称为“文件排序”

此时,已有的索引无法满足sql需要

当出现Using temporary和Using filesort的时候,说明这条sql的效率比较低,这个时候就需要优化一下sql或者索引结构了。

(二)使用explain的综合分析小案例

SQL:select emp.age,dep.d_name from employee emp left join department dep on emp.dep_id=dep.id where emp.name='niky' order by dep.id ;

通过explain我们可以看到id列都为1,所以执行顺序将从上到下依次执行;没有使用子查询或者其他复杂的连接,所以此处的select_type为simple;查询使用的连接类别为ref和eq_ref,说明使用到了索引,查询的性能尚可;possible_key和key保持一致,没有出现索引失效的情况;ref列的值说明了两段查询中使用到了匹配值分别为常量和emp表的dep_id字段;Extra列中显示该sql语句中使用到了临时表和文件内排序,原因是两表关联后根据dep表的id字段排序,没有使用到索引。

这里的话,我们可以改用排序条件来优化sql。

优化前

优化后

相关建表sql参考

-- ----------------------------

-- Table structure for department

-- ----------------------------

DROP TABLE IF EXISTS `department`;

CREATE TABLE `department` (

`id` int(11) NOT NULL,

`d_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,

PRIMARY KEY (`id`) USING BTREE

) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Compact;

-- ----------------------------

-- Records of department

-- ----------------------------

INSERT INTO `department` VALUES (1, 'HR');

INSERT INTO `department` VALUES (2, 'FI');

INSERT INTO `department` VALUES (3, 'RD');

INSERT INTO `department` VALUES (4, 'SD');

INSERT INTO `department` VALUES (5, 'MAR');

-- ----------------------------

-- Table structure for employee

-- ----------------------------

DROP TABLE IF EXISTS `employee`;

CREATE TABLE `employee` (

`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '员工id',

`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL COMMENT '员工姓名',

`dep_id` int(11) NULL DEFAULT NULL COMMENT '所属部门id',

PRIMARY KEY (`id`) USING BTREE

) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Compact;

-- ----------------------------

-- Records of employee

-- ----------------------------

INSERT INTO `employee` VALUES (1, 'amy', 1);

INSERT INTO `employee` VALUES (2, 'tony', 1);

INSERT INTO `employee` VALUES (3, 'jack', 4);

INSERT INTO `employee` VALUES (4, 'jony', 2);

INSERT INTO `employee` VALUES (5, 'niky', 3);

INSERT INTO `employee` VALUES (6, 'tini', 5);

INSERT INTO `employee` VALUES (7, 'itern', 10);

INSERT INTO `employee` VALUES (8, 'bob', 5);

mysql分析表关键字_SQL调优利器——explain关键字详解(MySQL)相关推荐

  1. JVM基础及JVM调优及常见参数详解

    什么是JVM 可以参考下面这篇文章 一篇文章掌握整个JVM,JVM超详细解析!!!_小杰要吃蛋的博客-CSDN博客_jvm 解析 常见JVM参数 -XX:+PrintGC 每次触发GC的时候打印相关日 ...

  2. JVM性能调优监控工具hprof使用详解

    一.问题现状 现实企业级Java开发中,有时候我们会碰到下面这些问题: OutOfMemoryError,内存不足 内存泄露 线程死锁 锁争用(Lock Contention) Java进程消耗CPU ...

  3. 性能调优之iostat命令详解

    Linux系统中的iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视.它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况.同v ...

  4. mysql验证索引正确性_mysql调优--根据explain结果分析索引有效性,正确使用索引

    定位低效率sql 对于mysql性能优化,除了宏观层面的网络.设备等优化,sql语句的优化是极为重要的一环,需要想办法找到对应的执行效率低的sql语句进行优化. 慢查询日志 慢查询日志是定位低效率sq ...

  5. mysql myisam表分区_MySQL分区表的局限和限制详解

    禁止构建 分区表达式不支持以下几种构建: 存储过程,存储函数,UDFS或者插件 声明变量或者用户变量 可以参考分区不支持的SQL函数 算术和逻辑运算符 分区表达式支持+,-,*算术运算,但是不支持DI ...

  6. 《JVM调优》- Jstack指令详解

    概述 jstack命令用于打印指定Java进程.核心文件或远程调试服务器的Java线程堆栈的跟踪信息.换句话说,就是jstack能生成JVM当前时刻的线程快照,以此来定位线程出现长时间停顿的原因,最常 ...

  7. 《JVM调优》- Jmap指令详解

    Jmap 常见用途 生成JVM堆的dump文件 查看finalize执行队列 查看Java堆和方法区的详细信息 常用指令 jmap [option] <pid> jmap [option] ...

  8. mysql中like与rlike_MySQL中RLIKE运算符的使用详解-mysql教程-

    在MySQL中,RLIKE运算符用于确定字符串是否匹配正则表达式.它是REGEXP_LIKE()的同义词. 如果字符串与提供的正则表达式匹配,则结果为1,否则为0. 语法是这样的: expr RLIK ...

  9. mysql查询优化explain命令详解

    转载自 mysql查询优化explain命令详解 mysql查询优化的方法有很多种,explain是工作当中用的比较多的一种检查方式.explain翻译即解释,就是看mysql语句的查询解释计划,从解 ...

最新文章

  1. sql text转image_[转]故障分析 | 记一次 MySQL 主从双写导致的数据丢失问题
  2. 自动驾驶车辆何时实现?近期不会实现的五大原因
  3. java轩辕剑天之痕游戏攻略_轩辕剑之天之痕游戏攻略大全
  4. 《C champion》 为什么要学习C语言
  5. Tornado的同步API写法举例实现GET/POST/DELETE请求+Tornado获取post请求中的json数据(转载)
  6. 常用技巧 —— 位运算 —— 异或运算实现两个数的交换
  7. vscode多开远程链接矩池云服务器
  8. IT民工系列——c#控制Word的类库。对com操作进行了封装
  9. 设计模式系列 — 模板方法模式
  10. 【高效开发插件】06 FEHelper 数据格式化
  11. 为啥苹果手机连无线无网络连接服务器,苹果手机网络无法连接怎么回事
  12. \t转义字符占几个字节?
  13. 乐高机器人纲要_人工智能与机器人课程纲要
  14. 海康萤石的本地在线码流
  15. SQL注入绕过(passby)策略
  16. 袁卫统计学第4版笔记和课后习题答案
  17. 在Spydroid-ipcamera基础上做推流的实现之二
  18. npm-install 命令报错4048的几种情况和解决方法
  19. 最适合python程序员用的笔记本-5款Python程序员高频使用开发工具推荐
  20. 【180930】C#纸牌小游戏源码

热门文章

  1. 记一次自己尴尬的飞机经历
  2. 信息管理毕设 基于SSM的停车位短租网站(含源码+论文)
  3. android中直播接受的一方
  4. 对python有兴趣
  5. 启动腾讯软件出现 应用程序无法启动并行配置不正确 解决
  6. 阿里云飞天会员体系企业用户及个人用户准入门槛说明
  7. 通过实时日志分析_进行访问日志的快速统计
  8. linux/kali NAT网络连接修复
  9. 2019c语言程序设计试题答案,2019年C语言程序设计期末考试试题及其答案【Word版资料】...
  10. VUE+WebPack:开发一款太空版植物大战僵尸的前端页游