5、type ☆
type标明了执行一条查询时对于mysql中一张表的访问方法。这是一个重要的指标,表示我们究竟是通过什么方式访问获取数据的。
完整的访问方法如下: system , const , eq_ref , ref , fulltext , ref_or_null ,index_merge , unique_subquery , index_subquery , range , index , ALL。
下面将详细的讲解。
- system
当表中只有一条记录,并且该表中存储引擎统计数据是精确的,比如MYISAM,Memory,那么其访问方法就是System。这种方式几乎是性能最高的,当然我们几乎用不上。
CREATE TABLE t(i int) Engine=MyISAM;
INSERT INTO t VALUES(1);
EXPLAIN SELECT * FROM t;
查询结果如下。
但凡我们再插入一条数据。
INSERT INTO t VALUES(2);
EXPLAIN SELECT * FROM t;
其访问方式就变成了性能最差的全表扫描ALL。
如果存储引擎是InnoDB,即使只有一条数据,其访问方式也是ALL,这是因为InnnoDB访问数据不是精确的。
- Const
当我们根据主键或者唯一的二级索引,与常数进行等值匹配时,对单表的访问方法就是const。这个访问方式的效率低于system,但也是很高效的。
比如对主键与常数匹配,进行等值查询。
EXPLAIN SELECT * FROM s1 WHERE id = 10005;
比如对Unique标识的唯一二级索引key2与常数匹配,进行等值查询。
EXPLAIN SELECT * FROM s1 WHERE key2 = 10066;
(4)eq_ref
再进行连接查询时,如果被驱动表是通过主键或者唯一二级索引等值匹配的方式进行查询的,那么被驱动表的访问方式是eq_ref。这也是一种性能很不错的方式。
EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.id = s2.id;
1
上面连接查询语句,对于驱动表来说,就是对s1全表进行扫描,找到符合条件的数据,因此其type是All,对被驱动表来说,相于直接访问驱动表查询到的数据进行等值查询,因此其访问方式是eq_ref.
(5)ref
当使用普通的二级索引与常量进行等值匹配时,type是ref。
EXPLAIN SELECT * FROM s1 WHERE key1 = ‘a’;
1
结果如下。
下面考考你。以下sql的引用类型是什么呢?
EXPLAIN SELECT * FROM s1 WHERE key3 = 10066;
1
看看答案。你是不是猜错了。是All。这是因为key3的字段是varchar类型,但是我们这里常量值是整形,因此需要使用函数进行隐式的类型转换,一旦使用函数,索引就失效了,因此访问类型变成了全表扫描All
我们常量使用对的类型。
EXPLAIN SELECT * FROM s1 WHERE key3 = ‘10066’;
1
就是期望的ref访问类型了。
(6)ref_or_null
当使用普通的二级索引进行等值匹配时,当索引值可以是Null时,type是ref_or_null。
EXPLAIN SELECT * FROM s1 WHERE key1 = ‘a’ OR key1 IS NULL;
1
结果如下。
(7)index_merge
当进行单表访问时,如果多个查询字段分别建立了单列索引,使用OR连接,其访问类型是index_merge。
EXPLAIN SELECT * FROM s1 WHERE key1 = ‘a’ OR key3 = ‘a’;
1
其结果如下。同时还可以看到key这一字段,是使用了两个索引。
猜猜下面sql的引用类型
EXPLAIN SELECT * FROM s1 WHERE key1 = ‘a’ AND key3 = ‘a’;
1
猜对了吗?答案是ref,这是因为用AND连接两个查询时,实际上只使用了key1的索引。
(8)unique_subquery
针对一些包含IN的subcase,如果优化器决定将IN子查询优化为EXIST子查询,而且子查询可以使用主键进行等值匹配的话,子查询的执行计划的type就是unique_subquery。
EXPLAIN SELECT * FROM s1 WHERE key2 IN (SELECT id FROM s2 where s1.key1 = s2.key1) OR key3 = ‘a’;
1
结果如下。
(9)range
范围查找的访问计划类型是range.
EXPLAIN SELECT * FROM s1 WHERE key1 IN (‘a’, ‘b’, ‘c’);
1
(10)index
当我们可以使用索引覆盖,但是需要扫描的全部的索引记录时,该表的访问方式就是index.索引覆盖后面文章介绍优化器时会详细介绍,为了便于大家理解,先简单介绍如下。比如下面sql语句中,key_part2 ,key_part2 都属于联合索引 INDEX idx_key_part(key_part1, key_part2, key_part3)的一部分,在查找数据时可以用上这个联合索引,而不用进行回表操作,这种情况即使索引覆盖。
EXPLAIN SELECT key_part2 FROM s1 WHERE key_part2 = ‘a’;
1
结果如下。