接着上篇文章《mysql执行计划分析(explain)的简单介绍说明》 继续讲讲 MySQL 的执行计划(EXPLAIN)中的type 字段,由于type字段的详细说明篇幅较长,并且在分析SQL语句的执行性能上也是特别需要关注的重点,所以奶嘴单独开一片文章来详细讲解。
type字段在 MySQL 官网文档描述如下:
The join type. For descriptions of the different types.
即连接类型,join在 MySQL 其实有很多种含义,通常一说到join大家都会联想到left join、inner join之类的,其实在每一次的sql查询都是join,这里的join我们可以理解为获取数据的方式,join type用什么样的方式来获取数据,通常情况下type字段可以很直观的体现出 MySQL 语句的性能。都有以下这些值(顺序,性能从高到低):
system
当表里面只有一行数据的时候就会这样,而且不管有没有索引都一样,这是const连接类型的特殊情况。
const
当查询只有唯一的一条记录被匹配,并且使用主键等于常数或者唯一索引等于某常数作为查询条件时, MySQL 会视查询出来的值为常数,这种类型非常快。和system不同的地方是system是表里面只有一行数据,而const有多行数据,const是只有一行数据被匹配。例如以下查询:
mysql> SELECT * FROM table_name WHERE id = 1
mysql> SELECT * FROM table_name WHERE phone = "18866666666"
以上SQL中的id字段表示主键(PRIMARY KEY),phone表示唯一索引(UNIQUE)。
eq_ref
对于前一个表中的每个行组合,只从该表中读取一行。除了system和const类型之外,这是最好的连接类型。只有当联接使用索引的部分都是主键或惟一非空索引时,就会出现这种类型。例如以下查询:
mysql> SELECT * FROM table1,table2 WHERE table1.id = table2.id;
ref
如果理解了eq_ref类型的话那么ref类型就也很好理解了,当联接使用索引的部分不是主键或惟一非空索引或或者使用了最左前缀索引(包括唯一索引和主键的),就会出现这种类型,表示连接的键使用了多行。
mysql> SELECT * FROM table WHERE name = 'naizui'
mysql> SELECT * FROM table1,table2 WHERE table1.name = table2.name
上面的两条SQL语句中的name字段都是普通索引。
fulltext
这个没什么好解释的,字面意思在使用了全文索引的情况下就会出现这种情况。
ref_or_null
和ref类似,但是如果当被索引的字段可以为NULL时,就又可能出现这种情况,比如说执行了以下类似的SQL语句:
mysql> SELECT * FROM table WHERE name = 'tom' OR name IS NULL
index_merge
表示使用了索引合并优化,每个索引单独使用,再通过某种算法来合并结果。
unique_subquery
子查询类型的eq_ref,表示子查询返回了多列,但是每一列的值都只匹配一条记录。例如执行了以下类似的SQL(user.id字段为唯一索引):
mysql> SELECT * FROM marry WHERE user_id IN( SELECT id FROM user WHERE height < 180 );
index_subquery
子查询类型的ref,和unique_subquery的关系类似于eq_ref和ref,表示子查询返回了多列,但是每一列都会匹配多个记录。 例如执行了以下类似的SQL (user.name字段为普通索引) :
mysql> SELECT * FROM marry WHERE name IN( SELECT name FROM user WHERE height < 180 );
range
表示使用了范围类型的查询,一般出现在使用了=, <>, >, >=, , BETWEEN, LIKE, 货 IN() 之类的字句和常量值作比较时,剧几个简单的例子:
mysql> SELECT * FROM tbl_name WHERE key_column = 10;
mysql> SELECT * FROM tbl_name WHERE key_column BETWEEN 10 and 20;
mysql> SELECT * FROM tbl_name WHERE key_column IN (10,20,30);
mysql> SELECT * FROM tbl_name WHERE key_part1 = 10 AND key_part2 IN (10,20,30);
index
和后面要介绍的all类型差不多,也是全表扫描,不过index有两种情况:
如果是覆盖索引的情况下,只扫描整个索引树,这种情况要比all类型的全表扫描要快。
按索引顺序扫描全表,几乎和all类型没有区别。
all
性能最差的类型,全表扫描。
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可,非商业性质可转载须署名链接,详见本站版权声明。