sql优化学习笔记之EXPLAIN详解

创建一张表

sql优化学习笔记之EXPLAIN详解_第1张图片

善用EXPLAIN查看执行计划

sql优化学习笔记之EXPLAIN详解_第2张图片

这里我们需要关注的数据有:

type列,key列,key_len列,rows列,extra列

1、type列

这里的type官方全称是“join type”,意思为连接类型,它更确切的说是一种数据库引擎查找表的一种方式,在《高性能mysql》一书中作者更是觉得称呼它为访问类型更贴切一些。mysql5.7中type的类型达到了14种之多,这里只记录和理解最重要且经常遇见的六种类型,它们分别是all,index,range,ref,eq_ref,const。从左到右,它们的效率依次是增强的。撇开sql的具体应用环境以及其他因素,你应当尽量优化你的sql语句,使它的type尽量靠右,但实际运用中还是要综合考虑各个方面的。一个好的SQL语句至少要达到range级别。杜绝出现all级别。

all:全表扫描,最原生的状态,有很大的优化空间 

此时表没有添加索引

sql优化学习笔记之EXPLAIN详解_第3张图片

index:这种连接类型只是另外一种形式的全表扫描,只不过它的扫描顺序是按照索引的顺序。这种扫描根据索引然后回表取数据,和all相比,他们都是取得了全表的数据,而且index要先读索引而且要回表随机取数据,因此index不可能会比all快(取同一个表数据),但为什么官方的手册将它的效率说的比all好,唯一可能的原因在于,按照索引扫描全表的数据是有序的。这样一来,结果不同,也就没法比效率的问题了。
如果一定要比效率,只需要获取这个表的数据并且排序便可以看出来谁比谁效率高了:

sql优化学习笔记之EXPLAIN详解_第4张图片

sql优化学习笔记之EXPLAIN详解_第5张图片

range:range指的是有范围的索引扫描,相对于index的全索引扫描,它有范围限制,因此要优于index。关于range比较容易理解,需要记住的是出现了range,则一定是基于索引的。同时除了显而易见的between,and以及'>','<'外,in和or也是索引范围扫描。

ref:出现该连接类型的条件是: 查找条件列使用了索引而且不为主键和unique。其实,意思就是虽然使用了索引,但该索引列的值并不唯一,有重复。这样即使使用索引快速查找到了第一条数据,仍然不能停止,要进行目标值附近的小范围扫描。但它的好处是它并不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内扫描。下面为了演示这种情形,给employee表中的name列添加一个普通的key(值允许重复)

此时给列v2加上普通索引(值允许重复)

sql优化学习笔记之EXPLAIN详解_第6张图片

eq_ref:ref_eq 与 ref相比牛的地方是,它知道这种类型的查找结果集只有一个?什么情况下结果集只有一个呢!那便是使用了主键或者唯一性索引进行查找的情况。多在基于唯一索引的连表查询的时候出现,这可能是最好的联接类型。

const:通常情况下,如果将一个唯一索引(主键也是一个特殊的唯一索引)放置到where后面作为条件查询,mysql优化器就能把这次查询优化转化为一个常量。至于如何转化以及何时转化,这个取决于优化器。

2、key列,使用到的索引名。如果没有选择索引,值是NULL。要让mysql强行使用或者忽略在 possible_keys字段中的索引列表,可以在查询语句中使用关键字force index, use index,或 ignore index

3、key_len列,显示了mysql使用索引的长度。当 key 字段的值为 null时,索引的长度就是 null。注意,key_len的值可以告诉你在联合索引中mysql会真正使用了哪些索引。

4、rows列,扫描行数。这个数表示mysql要遍历多少数据才能找到,在innodb上是不准确的,是个预估值。

5、extra列,详细说明。如果是Only index,这意味着信息只用索引树中的信息检索出的,这比扫描整个表要快。
如果是where used,就是使用上了where限制。
如果是impossible where 表示用不着where,一般就是没查出来啥。

注意,常见的不太友好的值,如下:Using filesort,Using temporary,意思为WHERE和ORDER BY的索引经常无法兼顾,如果按照WHERE来确定索引,那么在ORDER BY时,就必然会引起Using filesort,这就要看是先过滤再排序划算,还是先排序再过滤划算。

Using filesort
MySQL需要额外的一次传递,以找出如何按排序顺序检索行。

Using temporary
为了解决查询,MySQL需要创建一个临时表来容纳结果。

你可能感兴趣的:(sql优化学习笔记)