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. RabbitMQ一个简单可靠的方案(.Net Core实现)

    前言 最近需要使用到消息队列相关技术,于是重新接触RabbitMQ.其中遇到了不少可靠性方面的问题,归纳了一下,大概有以下几种: 1. 临时异常,如数据库网络闪断.http请求临时失效等: 2. 时序 ...

  2. Service Fabric是什么?

    题记:鉴于社区对Service Fabric有诸多误解,希望借本文能让大家正确了解Service Fabric是一个什么东西,算是给其正名. 术语与分类 Service Fabric不仅仅是容器编排器 ...

  3. SLogViewer下载及使用说明

    SLogViewer 1.0使用说明 SLogViewer是一个基本开源界面库SOUI开发的开源的通用的高性能LOG分析工具, 轻松支持上百万行级别的LOG过滤.  支持LOG格式配置. 只要是固定格 ...

  4. session的创建和销毁时间

    什么时候创建session ? 在你的服务器端发现没有该客户端的session,那么创建 什么时候销毁? 1.关闭客户端的时候 2.手动销毁 3.过期

  5. SQL Server 分区表上建立ColumnStore Index 如何添加新分区方法与步骤

    在生产环境中会遇到这样的场景,一个表随着时间的推移,越来越大,这个时候我们开始动手为这个表建立分区来改进查询性能. 但是表过大上百个G的时候,在数据仓库中,为了改进查询性能,我们可以添加在分区表的基础 ...

  6. 利用kibana插件对Elasticsearch进行映射

    映射(mapping) 映射是创建索引的时候,可以预先定义字段的类型以及相关属性 Elasticsearch会根据JSON源数据的基础类型去猜测你想要的字段映射.将输入的数据变成可搜索的索引项.Map ...

  7. Java中的异步通知

    在我们的日常开发中,经常会遇到这样的问题--"我让你做一件事情,但是你做得很慢,并不能够立马返回给我结果,害我一直在那儿等着你给我返回结果,什么都做不了". 程序是自上而下顺序执行 ...

  8. connector for python实验

    MySQL 是最流行的关系型数据库管理系统,如果你不熟悉 MySQL,可以阅读 MySQL 教程. 下面为大家介绍使用 mysql-connector 来连接使用 MySQL, mysql-conne ...

  9. jquery获取一组文本框的值

    $("#btn5").click(function()  {    var str="";$("[name='checkbox'][checked]& ...

  10. java方法的调用

    各种方法的调用实例 package cn.edu.fhj.day004; public class FunctionDemo { // 定义全局的变量 public int a = 3; public ...