MySQL优化Explain命令简介(二)

type列

MySQL手册上注明type列用于描述join type,不过我们认为把这一列视为对access type--即MySQL决定如何在表中寻找数据的方式的描述,更加合适一些,以下所示从最坏情况到最好情况下的access类型:

ALL

All类型即常说的全表扫描,通常意味着MySQL需要从头到尾扫描整张表以找到符合条件的行记录(使用LIMIT限定的查询语句个例外,一般在extra列中会有"Using distinct/not exists"的补充描述)。

index

基本和全表扫描一样,但是是通过索引的顺序扫描,主要优化是避免了排序,最大的缺点是通过索引顺序扫表时,通常意味着从存储空间中乱序取数据,IO花销会非常大。

如果在Extra列中还有"Using index"的说明,意味着MySQL使用一个覆盖索引实现扫表,而不是使用索引顺序扫表,这会比通过索引顺序扫表具有更好的性能。

range

一个范围遍历是一个限制版本的索引遍历,从索引中的某个位置开始,返回一定范围内的所有行记录,这会比扫描整个索引更快,这类查询的where子句中一般伴有BETWEEN或者>这类关键词。

当MySQL使用索引查找IN或者OR包含的一系列值时,也会显示为一个范围遍历,但是这两种其实是非常不同的访问类型,两者之间有着重要的性能差异。

ref

这是一个返回匹配特定单一值行记录的索引访问(索引查找)类型,实际上由于可能存在多行匹配的情况,这是一个查找和遍历的混合类型。这种索引查找仅能用于非唯一索引或者一个唯一索引的非唯一前缀索引。之所以叫做ref类型是因为索引被用于和一些参考值(reference value)进行比较,参考值只能一个常量或者多表查询中之前一个表中的某个值。

ref_or_null是ref的一个变种,意思是MySQL在做了第一次查找后,还必须做第二次查找查找为NULL的记录。

eq_ref

这是MySQL知道最多只会返回一个匹配结果的索引查找类型。当针对主键或者唯一索引和一些引用值比较时,就是这种访问类型,MySQL能针对这种类型做非常好的优化,因为不需要预估匹配行记录的范围或者在找到一行记录后再继续查找。

const,system

当MySQL能够将查询中的某些部分优化为一个常量时,就是这中访问类型。如果你将主键放置在where子句中,同时在select部分选取该主键,MySQL就会将其转化为一个常量,然后从join执行中高效的移除这个表。

NULL

NULL访问类型标识MySQL在优化阶段就能解析查询,甚至不需要在执行阶段实际访问到表数据或者索引,例如从索引列中获取最小值,只需要查看一下索引,不要求执行期间访问任何表数据。

possible_keys列

这一列基于查询语句中访问到和用于比较操作的列名,展示那些可能用于查询的索引名称列表,这个列表在优化阶段的早期生成,所以在经过后面的优化阶段后,其中的一些索引可能就并不需要用到了。

key列

这一列展示MySQL实际使用哪个索引优化对于表的访问,如果这个索引没有出现在possible_keys中,表明MySQL是基于其他特殊理由选定的该索引--比如即便查询没有where子句,MySQL也可能会优先选择使用覆盖索引。

换句话所,possible_keys揭示了哪些索引能够帮助行记录查询更加高效,而key则显示了优化器实际决定使用来最小化查询花销,下面是一个实际例子。

key_len列

这一列展示MySQL使用的索引的长度(字节个数),如果MySQL只使用索引中的一部分列,可以通过这个值计算出MySQL实际使用的是哪些列。注意MySQL5.5及以下版本只能使用最左前缀匹配。下面这个例子中sakila.film_actor的主键包括两个SMALLINT列,一个SMALLINT是两个字节,所以主键索引长度应该是4字节:

根据key_len,我们能推断出上面的查询语句仅在第一列(actor_id)上使用了索引查找。当计算列使用情况时,还需要考虑到字符类型列字段实际使用的字符集:

上面查询中a列和b列组成的索引长度为13字节,a列只有三个字符大小,但是utf8字符集使用最多3个字节标识一个字符,b列则是4字节整数。

MySQL并不总是会告诉你一个索引被多大程度使用到,如果你使用一个前缀匹配的LIKE查询,它将显示被使用那一列的总长度。

key_len列标识索引字段可能被使用到的最大长度,而不是表中数据使用的实际字节数量,即便上面的列a凑巧不包含任何长度大于一字符的值,MySQL依然会显示13字节长度,也就是说,key_len是通过表的定义计算得出,而非表中的实际数据。

ref列

这字段标识之前的表中哪些列或者常量被用于key列中的索引进行查找,下面是一个join和alias使用的例子,注意ref列反映了film表在查询语句中怎么被别称为f:

rows列

这一列展示MySQL估计查询语句执行时需要实际读取数据的记录行数,针对一个多重嵌套查询的语句,这个数字并不只是MySQL认为他需要从表中读取的实际行数,它将是每一个子查询阶段中MySQL估计满足当前查询条件所需要读取的行数。

根据表的统计信息已经索引的选择情况,这个估计可能很不准,MySQL5.0及以前,不会考虑LIMIT的影响,如下例:

你可以通过将每一行中这列的值相乘以得到整个查询语句大概要检查的行记录数量,如下例大概会检查2600行记录:

注意这个数量是MySQL估计会检查的行数,并不是结果集中的行数,并且诸如连接缓存这些优化,并不会影响到这一行的数值,即便MySQL可能并不会实际检查它估计的每一行数据,MySQL也不知道操作系统或者硬件缓存所做的任何优化。

filtered列

当使用EXPLAIN EXTENDED时,MySQL5.1及以上版本会有这一列,它针对满足where语句或者join条件的行数百分比做一个悲观估计,如果将rows列的数值乘以这个百分比,可以得到MySQL估计其会与前面的表数据进行join的行数量,优化器使用这一估计应用于ALL/index/range和index_merge访问类型。

假设下面一个标结构:

往表中插入1000条filler为随机的文本数据,以避免MySQL会针对我们的查询使用覆盖索引:

MySQL本可以使用一个range access通过ID从表中检查ID<500的行记录,但是考虑到这只能优化大概一半的行访问,它认为一个全表扫表的花销反而更少些,于是MySQL选择全表扫表时通过WHERE子句中的条件过滤行记录。通过range access的估计,MySQL能知道大概有多少行会被WHERE条件过滤,于是filtered列中的值就是49.40%了。

Extra列

这一列展示了其他列所没有的额外信息,MySQL文档上说明了能够出现在这一列的大多数值,你能够经常见到的最重要的一些取值如下:

Using index

MySQL会使用覆盖索引避免直接访问表数据,不要把覆盖索引和index访问类型弄混。

Using where

MySQL把数据从存储引擎中检索出来后,才会使用where条件进行过滤,WHERE子句中涉及到索引列的条件很多都可以在读取索引时被检测,所以并不是所有有WHERE子句的查询都会有“Using where”这一信息,有时候这个信息的存在暗示查询可能能够通过不同的索引策略获得优化。

Using temporary

MySQL会使用改一个临时表存储查询结果。

Using filesort

MySQL会对使用外部排序对结果排序,而不是通过索引顺序读取表数据,MySQL有两种filesort算法,都可以在内存或者硬盘上进行排序,EXPLAIN并不会指出具体使用的是哪种filesort算法,也不会指出是在内存还是硬盘上进行排序。

Range checked for each record(index map:N)

这意味着没有好的索引策略,join子句中的每一行都要重新计算索引,N表示possible_keys中的一个冗余的索引bitmap。

原文地址:https://www.cnblogs.com/AcAc-t/p/mysql_explain_1.html

时间: 2024-08-24 11:28:38

MySQL优化Explain命令简介(二)的相关文章

MySQL中EXPLAIN命令详解

explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了: 如: explain select surname,first_name form a,b where a.id=b.id EXPLAIN列的解释: table:显示这一行的数据是关于哪张表的 type:这是重要的列,显示连接使用了何种类型.从最好到最差的连接类型为const.eq_reg.ref.range.in

MySQL的Explain命令

Explain命令是查看查询优化器如何决定执行查询的主要办法. 调用 EXPLAIN 要使用EXPLAIN,只需在查询中的SELECT关键字之前增加EXPLAIN.MySQL会在查询上设置一个标记.当执行查询时,这个标记会使其返回关于在执行计划中每一步的信息,而不是执行它(一般情况下).它会返回一行或多行信息,显示出执行计划中的每一部分和执行的次序. explain select 1结果示例: 在查询中每个表在输出中只有一行.如果查询是两个表的连接,那么输出中将有两行.别名表单算为一个表.如果把

mysql优化--explain分析sql语句执行效率

Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好的优化语句. Explain语法:explain select - from - [where -] 例如:explain select * from news; 输出:+----+-------------+-------+-------+-------------------+---------+-

【MySQL】EXPLAIN命令详解

具体参考: https://www.cnblogs.com/gomysql/p/3720123.html 原文如下: 在工作中,我们用于捕捉性能问题最常用的就是打开慢查询,定位执行效率差的SQL,那么当我们定位到一个SQL以后还不算完事,我们还需要知道该SQL的执行计划,比如是全表扫描,还是索引扫描,这些都需要通过EXPLAIN去完成.EXPLAIN命令是查看优化器如何决定执行查询的主要方法.可以帮助我们深入了解MySQL的基于开销的优化器,还可以获得很多可能被优化器考虑到的访问策略的细节,以及

Mysql中explain命令查看语句执行概况

Mysql中可以使用explain命令查看查询语句的执行方式,使用方法举例:explain + 查询语句 例如:explain select * from user_info 几个重要的字段说明: table:此次查询操作是关联哪张数据表 type:连接查询操作类型,一般根据索引查询的话为const,如果没有索引,则遍历所有数据那么为All(此种方式效率极低) possible_keys:显示可能应用在这张表中的索引.如果为空,没有可能的索引. key: 实际使用的索引.如果为NULL,则没有使

MySQL的EXPLAIN命令详解(转)

explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了: 如: explain select surname,first_name form a,b where a.id=b.id EXPLAIN列的解释: table:显示这一行的数据是关于哪张表的 type:这是重要的列,显示连接使用了何种类型.从最好到最差的连接类型为const.eq_reg.ref.range.in

mysql优化--explain关键字

MySQL性能优化---EXPLAIN 参见:https://blog.csdn.net/jiadajing267/article/details/81269067 参见:https://www.cnblogs.com/clphp/p/5403215.html explain关键字用于分析sql语句的执行情况,可以通过他进行sql语句的性能分析. 对explain查询出来的结果含义进行分析: id值的含义: ? id为语句的查询序号,也就是查询的执行顺序,如果id值相同表示语句是自上而下的执行的

mysql数据库explain命令用法详解

本文转自一位前辈的文章,感觉写得很好,就转过来了.这个是那位前辈的原文地址:http://www.111cn.net/database/mysql/81698.htm 当我们在优化SQL时,想看看自己写的SQL的执行效率问题,MySql给我们提供一个命令explain,可以显示我们所写的SQL效率. 一个常见的理解错误:mysql在执行explain时不会执行sql语句,事实上如果查询的from字段有子查询,explain会执行子查询. explain只能解释select查询,对update,d

mysql优化----explain的列分析

sql语句优化: 1: sql语句的时间花在哪儿? 答: 等待时间 , 执行时间. 等待时间:看是不是被锁住了,那就不是语句层面了是服务端层面了,看连接数内存. 执行时间:到底取出多少行,一次性取出1万行那是你的sql语句写的失败,二是扫描多少行,扫描多少行需要技术来分析,通过explain来分析. 可以重构查询和切分查询. 2: sql语句的执行时间,又花在哪儿了? 答:a: 查 ----> 沿着索引查,甚至全表扫描b: 取 ----> 查到行后,把数据取出来(sending data) 3