标题
- explain函数
- type
- key
- extra
- rows
- 索引排序
前言,如无特殊提醒,默认建立如下索引。
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/fd959c0491c741deb353f316bd3c0ec9.png)
explain函数
type
type列反映了访问类型。表示mysql如何找到数据。访问类型有很多种,从全表扫描到索引扫描、范围扫描、唯一索引查询、常数引用等。这里列出的这些,速度从慢到快,扫描的行数从多到少:
all < index<range<req<const,你不需要记住这些访问类型,但需要明白扫描表、扫描索引、范围访问和单值访问的概念。
-
全表扫描all:顾名思义,就是扫描了整张表。age上没有任何联合或单个索引,id是主键。由于没有索引,所以执行时,去全表过滤age>10的数据。
-
索引扫描index:扫描了一颗B+树,比如聚簇索引、覆盖索引等。
举例:- 比如select id from dept。id是主键,走的聚簇索引。
- 建立联合索引:(db_source, dname, sex),
select dname from dept where db_source > 10;因为where过滤条件满足索引左前缀,所以是扫描的一颗索引树,而且查询的列是索引类,走的是覆盖索引查询。
而加入一个age列,这样索引树上每查询一次都还要回表一次,type列自然不是index而是all。
-
范围扫描range:
注意,这里where里面的列,也是需要走索引才行的。
因为如果没有索引的话,就走了全表扫描了,即all。
而且这里的条件需要满足最左前缀原则,否则成index,如下:
-
唯一索引查询ref或eq_ref:
一般是对主键或唯一索引进行等值查询,返回一条或多条数据。
如图建立普通联合索引(dbsource,dname,sex), -
常数const:
一般是对主键或唯一索引进行等值查询,返回一条数据。我觉得走聚簇索引就是这样。
key
key表明了我们用到了哪一个索引。这个“用”,也可能是直接查询,也可能是用来扫描的。
如图,where里面也没有满足最左前缀匹配呀?为什么显示还是走了索引呢?
知乎上讲8.0以后优化了啥的,但我的版本是5.7.33啊。(与数据量无关,我在8w的表里执行,结果一样)
我试着分析一下,
type是index,表示扫描了一颗索引树,而且查询的列都是索引列,应该走的是覆盖索引查询(extra列没截全,可以看下一个图)。所以key显示idx_thress的意思是:我用到了这个索引,因为不满足左前缀,不能精确查询,所以是用来扫描的。
当我们再加一个where条件时,type变为了ref,此时key为idx_threes表示:我用到了这个索引进行查询数据(注意这里的查找和上面的扫描是不同的)。由于是等值查询,所以type是ref
extra
using index:覆盖索引查询
using filesort:用到了文件排序
using where:见下面rows
rows
表示mysql查找结果,大概需要扫描多少行。这个值仅供参考。
一般地,MySQL能够使用如下三种方式应用WHERE条件,从好到坏依次为:
●在索引中使用WHERE条件来过滤不匹配的记录。这是在存储引擎层完成的。
●使用索引覆盖扫描(在Extra列中出现了Using index)来返回记录,直接从索引中过滤不需要的记录并返回命中的结果。这是在MySQL服务器层完成的,但无须再回表查询记录。●从数据表中返回数据,然后过滤不满足条件的记录(在Extra列中出现Using where)。这在MySQL服务器层完成,MySQL需要先从数据表中读出记录然后过滤。
索引排序
MySQL有两种方式可以生成有序的结果:通过排序操作,或者按索引顺序扫描。如果在EXPLAIN的输出结果中,type列的值为“index”,则说明MySQL使用了索引扫描来做排序(注意,不要和Extra列的“Using index”搞混)。
扫描索引本身是很快的,因为只需要从一条索引记录移动到紧接着的下一条记录。但如果索引不能覆盖查询所需的全部列,那么就不得不每扫描一条索引记录都回表查询一次对应的记录。这基本上都是随机I/O,这样比顺序地全表扫描都慢。
有两种方式,1.where 条件和order by的字段组合起来满足最左前缀原则
2.order by里面的字段满足最左前缀。下面是两个例子:
排序时要和查询一样,order by中的字段都要满足最左前缀匹配规则 且 排序顺序要一致。如果查询需要联接多张表,则只有当ORDER BY子句引用的字段全部在第一个表中时,才能使用索引做排序。因为排序时字段可能来自多个表,而索引只能在单个表上建立奥。
另外一种:
ORDER BY子句不满足索引的最左前缀的要求,也可以用于查询排序,这正是因为索引的第一列被指定为了一个常数。
原文作者:WKP9418
原文地址:https://blog.csdn.net/qq_43179428/article/details/140819862