详解 MySQL 执行计划

EXPLAIN语句提供有关MySQL如何执行语句的信息。EXPLAIN与SELECT,DELETE,INSERT,REPLACE和UPDATE语句一起使用。

EXPLAIN为SELECT语句中使用的每个表返回一行信息。它按照MySQL在处理语句时读取它们的顺序列出了输出中的表。 MySQL使用嵌套循环连接方法解析所有连接。这意味着MySQL从第一个表中读取一行,然后在第二个表,第三个表中找到匹配的行,依此类推。处理完所有表后,MySQL输出所选列,并通过表列表回溯,直到找到一个表,其中有更多匹配的行。从这个表中读取下一行,然后继续处理下一个表。

1.  EXPLAIN 输出列

说下几个关键的列:

  • type :连接类型
  • possible_keys :可选的索引
  • key :实际执行时使用的索引
  • ref :ref列显示将哪些列或常量与前面key列中显示的命名的索引进行比较以从表中选择行
  • rows :rows列表示MySQL认为执行查询必须检查的行数

2.  连接类型

连接类型,顺序从最好到最差,依次是:

system

表只有一行。这是const join类型的特例。

const

表最多有一个匹配行,在查询开始时读取。因为只有一行,所以这一行中的列的值可以被优化器的其余部分视为常量。const表非常快,因为它们只被读取一次。

当你用PRIMARY KEY或UNIQUE索引的所有部分与常量值进行比较时,将使用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;

eq_ref

对于前表中的每一行组合,从这个表中读取一行。除了system和const类型,这是可能的最好的联接类型。当一个索引的所有部分都被联接使用并且索引是PRIMARY KEY或UNIQUE NOT NULL索引时,使用它。

eq_ref可以用于使用=操作符进行比较的索引列。比较值可以是一个常量,也可以是使用在此表之前读取的表中的列的表达式。

例如,下面的例子中MySQL可以使用eq_ref连接来处理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

对于前表中的行的每种组合,将从该表中读取具有匹配索引值的所有行。如果联接仅使用key的最左前缀,或者如果key不是PRIMARY KEY或UNIQUE索引(换句话说,如果联接无法基于key值选择单个行),则使用ref。如果使用的key仅匹配几行,则这是一种很好的联接类型。

ref可用于使用=或<=>运算符进行比较的索引列。

例如,下面的例子中,MySQL可以用ref连接来处理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

使用FULLTEXT索引执行连接

ref_or_null

这种连接类型类似于ref,但是MySQL会额外搜索包含NULL值的行。此联接类型优化最常用于解析子查询。

例如,下面的例子中,MYSQL可以使用ref_or_null来处理ref_table:

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

index_merge

这种连接类型表明使用了索引合并优化。在这种情况下,输出行中的key列包含使用的索引列表,而key_len包含所使用索引的最长key部分列表。

unique_subquery

此类型将eq_ref替换为以下形式的某些IN子查询:

value IN (SELECT primary_key FROM single_table WHERE some_expr)

index_subquery

与unique_subquery类似,它代替了IN子查询,但适用于以下形式的子查询中的非唯一索引:

value IN (SELECT key_column FROM single_table WHERE some_expr)

range

只检索给定范围内的行,并使用索引来选择行。输出行中的key列指示使用了哪个索引。key_len包含所使用的最长的key部分。对于这种类型,ref列为NULL。

使用=,<>,>,> =,<,<=,IS NULL,<=>,BETWEEN,LIKE或IN()运算符将key列与常量进行比较时,可以使用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

index连接类型与all是一样的,区别在于index连接类型扫描的时候索引树。通常,只发生在以下两种情况:

  • 如果索引是查询的覆盖索引,并且可用于满足表中所需的所有数据,则仅扫描索引树。在这种情况下,“Extra”列显示“Using index”。仅索引扫描通常比ALL快,因为索引的大小通常小于表数据。
  • 使用从索引读取数据以按索引顺序查找数据行来执行全表扫描。“Uses index”不会出现在Extra列中。

ALL

对前表的行的每个组合进行全表扫描。如果该表是未标记为const的第一个表,则通常不好,并且在所有其他情况下通常非常糟糕。通常,可以通过添加索引来避免ALL,这些索引允许基于早期表中的常量值或列值从表中检索行。

3.  Extra列

关于Extra列的输出,只说几个常见的:

Using filesort

MySQL必须做一次额外操作,以找出如何按排序顺序检索行。排序是通过根据联接类型遍历所有行并存储与WHERE子句匹配的所有行的排序key和指向该行的指针来完成的。然后对key进行排序,并按排序顺序检索行。

Using index

仅使用索引树中的信息从表中检索列信息,而不需要执行额外的查找来读取实际行。当查询只使用属于单个索引的列时,可以使用此策略。

Using temporary

为了解析查询,MySQL需要创建一个临时表来保存结果。通常,如果查询包含以不同方式展示列的GROUP BY和ORDER BY子句,则会发生这种情况。

Using where

WHERE子句用于限制哪些行匹配下一个表或发送给客户端。除非你打算从表中获取或检查所有行,否则如果额外的值没有使用where,并且表连接类型是all或index,则查询中可能出现错误。

4.  优化ORDER BY

在某些情况下,MySQL可能会使用一个索引来满足ORDER BY子句,从而避免执行filesort操作所涉及的额外排序。

假设在(key_part1, key_part2)上有一个索引,下面的查询可以使用索引来解析ORDER BY部分。优化器是否真的这样做,取决于如果还必须读取索引之外的时,读取索引是否比表扫描更有效。

SELECT * FROM t1 ORDER BY key_part1, key_part2;

上面的语句,查询使用SELECT *,这可能会选择比key_part1和key_part2更多的列。在这种情况下,扫描整个索引并查找表行以查找索引中未包含的列可能比扫描表并排序结果要昂贵。如果是这样,则优化器不太可能使用索引。如果SELECT *仅选择索引列,则使用索引并避免排序。

下面这个查询中,key_part1是常量,因此通过索引访问的所有行都按key_part2顺序排列,并且如果WHERE子句的选择性足以使索引范围扫描比表扫描便宜,则在(key_part1,key_part2)上的索引可以避免排序:

SELECT * FROM t1 WHERE key_part1 = constant ORDER BY key_part2; 

以上就是详解 MySQL 执行计划的详细内容,更多关于MySQL 执行计划的资料请关注我们其它相关文章!

(0)

相关推荐

  • mysql执行计划id为空(UNION关键字)详解

    简介 在工作过程中,有时候会对慢查询进行调优.对于MySQL的SQL语句调优,MySQL本身提供了强大的explain关键字用于查询分析执行计划.本文主要给大家介绍了关于mysql执行计划id为空(UNION关键字)的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的 介绍吧 UNION 操作符用于合并两个或多个 SELECT 语句的结果集.例如,我有两个表,表1记录的是公司男员工的数据,包括年龄.姓名.职位.表2记录的是公司女员工的数据,包括姓名.家庭住址.手机号等字段.这时,

  • Mysql深入探索之Explain执行计划详析

    前言 如何写出效率高的SQL语句,提到这必然离不开Explain执行计划的分析,至于什么是执行计划,如何写出高效率的SQL,本篇文章将会一一介绍. 执行计划 执行计划是数据库根据 SQL 语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的. 使用explain关键字可以模拟优化器执行 SQL 查询语句,从而知道 MySQL 是如何处理你的 SQL 语句的,分析你的 select 语句或是表结构的性能瓶颈,让我们知道 select 效率低下的原因,从而改进我们的查询.

  • MySQL中通过EXPLAIN如何分析SQL的执行计划详解

    前言 在MySQL中,我们可以通过EXPLAIN命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序. 下面分别对EXPLAIN命令结果的每一列进行说明: .select_type:表示SELECT的类型,常见的取值有: 类型 说明 SIMPLE 简单表,不使用表连接或子查询 PRIMARY 主查询,即外层的查询 UNION UNION中的第二个或者后面的查询语句 SUBQUERY 子查询中的第一个 .table:输出结果集的表(表别名) .t

  • MySQL中执行计划explain命令示例详解

    前言 explain命令是查看查询优化器如何决定执行查询的主要方法. 这个功能有局限性,并不总会说出真相,但它的输出是可以获取的最好信息,值得花时间去了解,因为可以学习到查询是如何执行的. 调用EXPLAIN 在select之前添加explain,mysql会在查询上设置一个标记,当执行查询计划时,这个标记会使其返回关于执行计划中每一步的信息,而不是执行它. 它会返回一行或多行信息,显示出执行计划中的每一部分和执行次序. 这是一个简单的explain效果: 在查询中每个表在输出只有一行,如果查询

  • MySQL执行计划的深入分析

    前言 在之前的面试过程中,问到执行计划,有很多童鞋不知道是什么?甚至将执行计划与执行时间认为是同一个概念.今天我们就一起来了解一下执行计划到底是什么?有什么用途? 执行计划是什么? 执行计划,简单的来说,是SQL在数据库中执行时的表现情况,通常用于SQL性能分析,优化等场景. 一. 执行计划能告诉我们什么? SQL如何使用索引 联接查询的执行顺序 查询扫描的数据函数 二. 执行计划中的内容 SQL执行计划的输出可能为多行,每一行代表对一个数据库对象的操作 1. ID列 ID列中的如果数据为一组数

  • mysql执行计划介绍

    烂sql不仅直接影响sql的响应时间,更影响db的性能,导致其它正常的sql响应时间变长.如何写好sql,学会看执行计划至关重要.下面我简单讲讲mysql的执行计划,只列出了一些常见的情况,希望对大家有所帮助. 测试表结构: 复制代码 代码如下: CREATE TABLE `t1` (  `c1` int(11) NOT NULL DEFAULT '0',  `c2` varchar(128) DEFAULT NULL,  `c3` varchar(64) DEFAULT NULL,  `c4`

  • MySql中如何使用 explain 查询 SQL 的执行计划

    explain命令是查看查询优化器如何决定执行查询的主要方法. 这个功能有局限性,并不总会说出真相,但它的输出是可以获取的最好信息,值得花时间去了解,因为可以学习到查询是如何执行的. 1.什么是MySQL执行计划 要对执行计划有个比较好的理解,需要先对MySQL的基础结构及查询基本原理有简单的了解. MySQL本身的功能架构分为三个部分,分别是 应用层.逻辑层.物理层,不只是MySQL ,其他大多数数据库产品都是按这种架构来进行划分的. 应用层,主要负责与客户端进行交互,建立链接,记住链接状态,

  • MYSQL explain 执行计划

    使用方法,在select语句前加上explain就可以了: 如:explain select * from test1 EXPLAIN列的解释: table:显示这一行的数据是关于哪张表的 type:这是重要的列,显示连接使用了何种类型.从最好到最差的连接类型为const.eq_reg.ref.range.indexhe和ALL possible_keys:显示可能应用在这张表中的索引.如果为空,没有可能的索引.可以为相关的域从WHERE语句中选择一个合适的语句 key: 实际使用的索引.如果为

  • 详解 MySQL 执行计划

    EXPLAIN语句提供有关MySQL如何执行语句的信息.EXPLAIN与SELECT,DELETE,INSERT,REPLACE和UPDATE语句一起使用. EXPLAIN为SELECT语句中使用的每个表返回一行信息.它按照MySQL在处理语句时读取它们的顺序列出了输出中的表. MySQL使用嵌套循环连接方法解析所有连接.这意味着MySQL从第一个表中读取一行,然后在第二个表,第三个表中找到匹配的行,依此类推.处理完所有表后,MySQL输出所选列,并通过表列表回溯,直到找到一个表,其中有更多匹配

  • 详解MySQL执行原理、逻辑分层、更改数据库处理引擎

    用了那么长时间的MySQL,sql语句相信早已烂熟于心,于是,我就试着去了解它的执行原理,以下是我学习过程中的总结要点. 只要是B/S架构,都是会有客户端与服务端,mysql也不例外. 首先客户端发出一个请求,这个请求就是一个查询请求(Select),而它请求的对象就是服务端,服务端是怎么处理这项查询功能的呢? 逻辑分层 首先可以把服务端想象成一个大的容器,里面有四层结构,当一个请求过来后,将会执行这四层,执行一遍后才会返回给我们想要的结果. 第一层 :连接层 也就是说,我们客户端发送一个Sel

  • MySQL执行计划详解

    一.MySQL执行计划介绍 在MySQL中,执行计划的实现是基于JOIN和QEP_TAB这两个对象.其中JOIN类表示一个查询语句块的优化和执行,每个select查询语句(即Query_block对象)在处理的时候,都会被当做JOIN对象,其定义在sql/sql_optimizer.h. QEP_TAB是Query Execution Plan Table的缩写,这里的表Table对象主要包含物化表.临时表.派生表.常量表等.JOIN::optimize()是优化执行器的统一入口,在这里会把一个

  • 详解MySQL 查询语句的执行过程

    首先先简单的将一个查询语句背后MySQL做了什么捋一捋: 客户端发送一条查询给服务器. 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果.否则进入下一个阶段. 服务器端进行SQL解析,预处理,再由优化器生成对应的执行计划. MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询. 将结果返回给客户端. 接着我们就将这个过程中的这些步骤详细的进行展开. 1.客户端和服务器端之间的通信方式 客户端和服务器之间的通信是一种半双工的通信,即在同一时刻,只能有一方向另一方发送

  • 详解MySQL kill 指令的执行原理

    kill 指令有两种写法 " kill query + 线程 id "." kill connection(可缺省) + 线程 id ".分别表示关闭指定线程正在执行的语句.断开指定线程连接的客户端(如果有正在执行的操作会先停止执行的操作再关闭连接).但某些情况下使用 kill query 后使用 show processlist 查看 Command 列为 killed(表示 正在等待回收线程回收,还未回收),这是为什么呢? 在解答这个问题前,需要知道服务器端处理

  • 详解MySQL中EXPLAIN解释命令及用法讲解

    1,情景描述:同事教我在mysql中用explain,于是查看了一番返回内容的含义 2,现就有用处的内容做如下记录: 1,explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了: explain select count(DISTINCT uc_userid) as user_login from user_char_daily_gameapp_11 where uc_d

  • 详解MySQL InnoDB的索引扩展

    索引扩展,InnoDB通过将主键列附加到每个辅助索引中来自动扩展该索引.创建如下表结构: mysql> CREATE TABLE t1 ( -> i1 INT NOT NULL DEFAULT 0, -> i2 INT NOT NULL DEFAULT 0, -> d DATE DEFAULT NULL, -> PRIMARY KEY (i1, i2), -> INDEX k_d (d) -> ) ENGINE = InnoDB; Query OK, 0 rows

  • 详解MySQL 8.0 之不可见索引

    言 MySQL 8.0 从第一版release 到现在已经走过了4个年头了,8.0版本在功能和代码上做了相当大的改进和重构.和DBA圈子里的朋友交流,大部分还是5.6 ,5.7的版本,少量的走的比较靠前采用了MySQL 8.0.为了紧追数据库发展的步伐,能够尽早享受技术红利,我们准备将MySQL 8.0引入到有赞的数据库体系. 落地之前 我们会对MySQL 8.0的新特性和功能,配置参数,升级方式,兼容性等等做一系列的学习和测试.以后陆陆续续会发布文章出来.本文算是MySQL 8.0新特性学习的

  • 详解mysql中explain的type

    导语: 很多情况下,有很多人用各种select语句查询到了他们想要的数据后,往往便以为工作圆满结束了. 这些事情往往发生在一些学生亦或刚入职场但之前又没有很好数据库基础的小白身上,但所谓闻道有先后,只要我们小白好好学习,天天向上,还是很靠谱的. 当一个sql查询语句被写出来之后,其实你的工作只完成了一小半,接下来更重要的工作是评估你自己写的sql的质量与效率.mysql为我们提供了很有用的辅助武器explain,它向我们展示了mysql接收到一条sql语句的执行计划.根据explain返回的结果

随机推荐