1.what is explain(explain 是个什么东东)

explain(解释),在 Mysql 中 作为一个关键词,用来解释 Mysql 是如何执行语句,可以连接 select 、delete、insert、update 语句。

通常我们使用 explain 连接 一条 select 语句,查看运行状态,判断是否需要优化。

2.how to use explain(如何使用呢)

栗子:

explain select s.name,s.id,s.age,s.create_time from student s;

  

输出:

  

+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | s | NULL | ALL | NULL | NULL | NULL | NULL | 7 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

  

官方:

EXPLAIN  [explain_type]  explainable_stmt

explain_type: {
EXTENDED
| PARTITIONS
| FORMAT = format_name
} explainable_stmt: {
SELECT statement
| DELETE statement
| INSERT statement
| REPLACE statement
| UPDATE statement
}

输出的列名:

  • id : select 标识符
  • select_type:select 类型
select_type 可选值 含义
SIMPLE 简单的 select,没有使用 UNION 或者 子查询
PRIMARY 最外一层的 select
UNION UNION 中第二个或者后面的 select 语句
DEPENDENT UNION UNION 中第二个或者后面的 select 语句,依赖于外层的 select
UNION RESULT UNION 的结果
SUBQUERY 子查询的第一个 select
DEPENDENT SUBQUERY 子查询的第一个 select,取决于外层的 select
DERIVED 派生表
MATERIALIZED Materialized subquery
UNCACHEABLE SUBQUERY 无法缓存结果的子查询,必须为外部查询的每一行重新计算其结果
UNCACHEABLE UNION UNION 查询中不可缓存的子查询中的第二个或者后一个 select
  • table:输出行对应的表
  • partitions:匹配的分区
  • type:join 类型
  • possible_keys:可选的索引,可以通过 show index from tbl_name 查看表有哪些索引。
  • key:实际选择的索引
  • key_len:实际使用索引的长度
  • ref:与索引比较的列
  • rows:扫描行数的预估值
  • filtered:按表条件筛选的行的百分比
  • Extra:额外信息

3.重点关注的列

3.1 type 列

type 列描述了表的 join 类型,以下以 查询的最优到最差的排序列出了可能值:

  • system :当表只有一条数据(= system table)时,为 system 类型,是 const 类型的 特例。

  

  • const:当表最多只有一条数据相匹配时,为 const 类型。因为只有一行,所以优化器的其余部分可以将此行列中的值视为常量(constant)。const表非常快,因为它们只读一次。在使用 主键 或者 唯一索引 和常量比较时,即为 const 类型。

如下的查询,tbl_name 可以被用作 const 表:

SELECT * FROM tbl_name WHERE primary_key=1;

SELECT * FROM tbl_name
WHERE primary_key_part1=1 AND primary_key_part2=2;

  

栗子:

explain select s.* from student s where s.id = 1

输出:

+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | s | NULL | const | PRIMARY | PRIMARY | 8 | const | 1 | 100.00 | NULL |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

  

  • eq_ref:通常出现在多表 join 查询,并且 关联的字段是 主键 或者 唯一非空索引,即后表 只能匹配一条数据。

下面的示例,可以使用 eq_ref join  来处理 ref_table:

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;

  

  • ref:通常出现在多表 join 查询,关联使用了 最左前缀原则的索引 或者 关联的是非主键 或者 非 唯一索引(也就是说,join 不能根据索引选择 单行数据)

下面的示例,Mysql 可以使用 ref join 来处理  ref_table:

SELECT * FROM ref_table WHERE key_column=expr;

SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;

  

  • fulltext:使用全文索引执行 join
  • ref_or_null:在 ref 的基础上 , 另外还搜索了包含空值的行

下面的示例,Mysql 可以使用 ref_or_null join 来处理  ref_table::

SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;

  

  • index_merge: 合并索引优化
  • unique_subquery:子查询返回唯一主键。

形如下面的示例:

value IN (SELECT primary_key FROM single_table WHERE some_expr)

  

  • index_subquery:和 unique_subquery 类似,只不过在子查询中使用非唯一索引

形如下面的形式:

value IN (SELECT key_column FROM single_table WHERE some_expr)

  

  • range:当 索引和常量 使用 诸如=, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, LIKE, or IN()  进行比较时 ,可以使用 range.

例如:

SELECT * FROM tbl_name
WHERE key_column = 10; SELECT * FROM tbl_name
WHERE key_column BETWEEN 10 and 20; SELECT * FROM tbl_name
WHERE key_column IN (10,20,30); SELECT * FROM tbl_name
WHERE key_part1 = 10 AND key_part2 IN (10,20,30);

  

  • index:和 all 类似 ,只不过 扫描的是 索引树
  • all:全表扫描,可以通过增加 索引避免 全表扫描

3.2 keys 列:真正使用的索引

3.3 rows 列:扫描的记录数

4.使用 explain 提升查询性能案例分析

假设有如下的 sql:根据订单日期 和 店员id 查询 订单信息(已创建了订单日期的索引),查询结果返回 18条记录。

  SELECT * FROM orders
WHERE YEAR(o_orderdate) = 1992 AND MONTH(o_orderdate) = 4
AND o_clerk LIKE '%0223';

  

Explain 输出执行计划:

问题所在:

  • 根据 type 为 ALL , 查询进行了全表扫描,被扫描的记录 rows 为  150万。
  • possible_keys 和 ky 均为空 ,订单日期索引完全失效,原因在于被索引的字段使用了处理函数导致索引失效

4.1.修改sql 保证 订单日期索引正常,

 SELECT * FROM orders
WHERE o_orderdate BETWEEN '1992-04-01' AND '1992-04-30'
AND o_clerk LIKE '%0223';

  

重新使用 Explain 查看 执行计划:

发现:type 由 ALL 变为 range ,订单日期索引得以利用,被扫描的记录由 15万 降为 3.3万左右。

4.2.另一个优化点在 店员字段的过滤

为 店员字段创建索引:

CREATE INDEX i_o_clerk ON orders(o_clerk);

  

再次输出执行计划:

发现:基本上并没有什么变化,新建的索引没有被利用,原因在于 该字段是 模糊查询,过滤指定后缀的 店员信息。但是索引对于后缀过滤会失效(尽管索引对于前缀有效果)。

修改sql,全量过滤店员字段:

SELECT * FROM orders
WHERE o_orderdate BETWEEN '1992-04-01' AND '1992-04-30'
AND o_clerk LIKE 'Clerk#000000223';

  

再次输出执行计划:

发现:可用索引增加,真正使用的索引变为 店员字段上的索引,被扫描的行由 3.3万降为 1546。

4.3.对于多条件查询,可以考虑使用组合索引

创建如下索引:

CREATE INDEX io_clerk_date ON orders(o_clerk, o_orderdate)

  ** :这里将 o_clerk 放在 o_orderdate 之前,因为 o_orderdate 使用了 范围,更优的放在前面。

再次输出执行计划:

发现:使用了组合索引,被扫描记录即为输出的18条记录。效率已最优化。

多次优化的总结:

Type Possible keys Key Rows Scanned Duration (seconds) Extra info Rows returned
all NULL NULL 1.50M 1.201 Using where 18
range i_o_orderdate i_o_orderdate 32642 0.281 Using index condition; Using where 18
range i_o_orderdate, i_o_clerk i_o_clerk 1546 0.234 Using index condition; Using where 18
range i_o_orderdate, i_o_clerk, i_o_clerk_date i_o_clerk_date 18 0.234 Using index condition 18

【mysql】mysql 调优之 ——执行计划 explain的更多相关文章

  1. 数据库SQL调优之"执行计划"【未完待续】

    什么是“执行计划”?“执行计划”怎么用于SQL调优? 内容待添加... 参考文章: [1]写SQL要学会使用"执行计划" by 鹏霄万里展雄飞      

  2. SQL Server 性能调优 之执行计划(Execution Plan)调优

    SQL Server 存在三种 Join 策略:Hash Join,Merge Join,Nested Loop Join. Hash Join:用来处理没有排过序/没有索引的数据,它在内存中把 Jo ...

  3. MySQL 执行计划explain详解

    MySQL 执行计划explain详解 2015-08-10 13:56:27 分类: MySQL explain命令是查看查询优化器如何决定执行查询的主要方法.这个功能有局限性,并不总会说出真相,但 ...

  4. mysql性能调优与架构设计笔记

    1.mysql基本介绍 mysql支持多线程高并发的关系型数据库; 数据库存储引擎InnoDB.MyISAM; mysql快速崛起的原因就是他是开源的; 性能一直是mysql自豪的一大特点; 2.my ...

  5. MySQL性能优化总结___本文乃《MySQL性能调优与架构设计》读书笔记!

    一.MySQL的主要适用场景 1.Web网站系统 2.日志记录系统 3.数据仓库系统 4.嵌入式系统 二.MySQL架构图: 三.MySQL存储引擎概述 1)MyISAM存储引擎 MyISAM存储引擎 ...

  6. MySQL性能调优与架构设计——第9章 MySQL数据库Schema设计的性能优化

    第9章 MySQL数据库Schema设计的性能优化 前言: 很多人都认为性能是在通过编写代码(程序代码或者是数据库代码)的过程中优化出来的,其实这是一个非常大的误区.真正影响性能最大的部分是在设计中就 ...

  7. mysql之调优概论

    一  简介 咱们先不说cpu的频率,内存的大小(这个和索引一样重要,但不是本文讨论的内容),硬盘的寻道时间.想起mysql的调优,最起码的必须知道explain执行计划,慢sql日志,老旧的profi ...

  8. MySQL性能调优思路

    1.MySQL性能调优思路 如果一台服务器出现长时间负载过高 /周期性负载过大,或偶尔卡住如何来处理? 是周期性的变化还是偶尔问题?是服务器整体性能的问题, 还是某单条语句的问题? 具体到单条语句, ...

  9. MySQL性能调优与架构设计——第8章 MySQL数据库Query的优化

    第8章 MySQL数据库Query的优化 前言: 在之前“影响 MySQL 应用系统性能的相关因素”一章中我们就已经分析过了Query语句对数据库性能的影响非常大,所以本章将专门针对 MySQL 的 ...

随机推荐

  1. macos 命令行安装 ipa

    macos 命令行安装 ipa 苹果发神经后itunes已经无法在安装app了,如果有知道的兄弟可以告诉我啊 ideviceinstaller 使用这个开源项目可以在macos下安装app brew ...

  2. RabbitMQ教程

    1.引言 RabbitMQ——Rabbit Message Queue的简写,但不能仅仅理解其为消息队列,消息代理更合适.RabbitMQ 是一个由 Erlang 语言开发的AMQP(高级消息队列协议 ...

  3. react native 项目版本升级

    首先说明一下rn项目的一种相当顺滑升级方法: 1.全局安装react-native-git-upgrade npm i -g react-native-git-upgrade 2. 在项目目录下执行命 ...

  4. 使用Tornado异步接入第三方(支付宝)支付

    目前国内比较流行的第三方支付主要有支付宝和微信支付,博主最近研究了下如何用Python接入支付宝支付,这里我以Tornado作为web框架,接入支付宝构造支付接口. 使用Tornado异步接入支付宝支 ...

  5. G - Surf Gym - 100819S -逆向背包DP

    G - Surf Gym - 100819S 思路 :有点类似 逆向背包DP , 因为这些事件发生后是对后面的时间有影响. 所以,我们 进行逆向DP,具体 见代码实现. #include<bit ...

  6. Android 博客导航

    Android 博客导航 一. 基础知识 Android 常用知识点 Android 常见问题解决 Android 常用控件 控件常用属性 Material Design 常用控件 二.常用知识点 动 ...

  7. yum程序下载被占用

    Loaded plugins: fastestmirror, refresh-packagekit, security Existing lock /var/run/yum.pid: another ...

  8. 【2019雅礼集训】【CF 960G】【第一类斯特林数】【NTT&多项式】permutation

    目录 题意 输入格式 输出格式 思路 代码 题意 找有多少个长度为n的排列,使得从左往右数,有a个元素比之前的所有数字都大,从右往左数,有b个元素比之后的所有数字都大. n<=2*10^5,a, ...

  9. 勾勾街——一个专注于免越狱免签名的苹果ios APP打包生成的网站

    自涛舅舅研发的“苹果ios APP自助生成系统”上线以来,每天都有大量的用户注册和生成免越狱app,为什么? 因为我们有明显的技术优势,APP不需要上架appstore, 生成APP又不需要企业签名证 ...

  10. MyBatis(10)使用association进行分步查询

    (1)接口中编写方法 public Emp getEmpByStep(Integer id); public Dept getDeptById(Integer id); (2)Mapper文件 < ...