Explain详解与索引优化实践(2)

NULL:MySQL能够在SQL语句执行之前(即优化阶段)分析分解查询语句,在执行阶段用不着再访问表或索引。例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表,出现的频率不高。

const,system:MySQL能够对查询的某部分进行优化并将其转化成一个常量(可以看show warnings的结果)。用于主键索引或唯一索引的所有列与常数比较时,表最多有一个匹配行,读取1次,速度比较快。system是const的特例,表里只有一条记录匹配时为system。

执行SQL语句:EXPLAIN EXTENDED SELECT * FROM (SELECT * FROM film WHERE id=1) tmp

分析:上面的子查询SELECT * FROM film WHERE id = 1语句where后面id使用的是主键索引查询,主键是唯一的,所以查询结果一定是只有一条记录,对于明确知道结果集只有一条记录的查询,它的type为const类型,性能已经非常高了;而第一个select复杂查询的表只有一条记录,所以结果也肯定只有一条记录(第二个select子查询之前表中可能是多条记录),这种特例它的type为system类型,性能最高。

执行SQL语句:EXPLAIN EXTENDED SELECT * FROM (SELECT * FROM film WHERE id=1) tmp;  SHOW WARNINGS;

分析:用explain extended查看执行计划会比explain多一列filtered,该列给出一个百分比的值,这个值和rows列一起使用,可以估计出那些将要和explain中的前一个表进行连接的行的数目,前一个表就是指explain的id列的值比当前表的id小的表。explain extended还可以搭配show warnings一起使用,它可以给出一个优化建议,真正执行时是执行优化建议的那条SQL,但是如果是很复杂的SQL,它优化出来的结果可能都没你原先的SQL性能高。

eq_ref:主键索引或唯一索引的所有部分被连接使用,最多只会返回一条符合条件的记录。这可能是在const之外最好的连接类型了,简单的select查询不会出现这种type。

执行SQL语句:EXPLAIN SELECT * FROM film_actor LEFT JOIN film ON film_actor.film_id=film.id

分析:有两条记录,说明有2次查询, id相等,则从上往下执行,说明第1条先执行查询film_actor表,第2条左连接查询film表。左连接film表并关联film.id,由于film.id是唯一索引,film表只能关联一行记录,所以第2条select的type为eq_ref。

ref:相比eq_ref,不使用唯一索引,而是使用普通索引或者唯一索引的前缀部分,索引要和某个值相比较,可能会找到多条符合条件的记录。

① 简单select查询,name是普通索引(非唯一索引)

执行SQL语句:EXPLAIN SELECT * FROM film WHERE

② 关联表查询,idx_film_actor_id是film_id和actor_id的联合索引,这里使用了film_actor的索引左边前缀部分 film_id。

执行SQL语句:EXPLAIN SELECT * FROM film LEFT JOIN film_actor ON film.id=film_actor.film_id

range:范围扫描通常出现在in(),between,>,<,>=等操作中。使用一个索引来检索给定范围的行。

执行SQL语句:EXPLAIN SELECT * FROM actor WHERE id>1

index: 扫描全表索引,这通常会比ALL快一些。(index是从索引中读取的,而ALL是从硬盘中读取)

执行SQL语句:EXPLAIN SELECT * FROM film;(film表所有字段都加了索引)

ALL: 即全表扫描,意味着MySQL需要从头到尾去查找所需要的行(不走索引)。通常情况下这需要增加索引来优化了。

执行SQL语句:EXPLAIN SELECT * FROM actor;(actor表有一个字段没加索引)

(5)possible_keys列

这一列显示查询可能使用哪些索引来查找。

explain时可能出现possible_key有列,而key显示NULL的情况,这种情况是因为表中数据不多,MySQL认为索引对此查询帮助不大,选择了全表查询。

如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查where子句是否可以创造一个适当的索引来提高查询性能,然后用explain查看效果。

(6)key列

这一列显示MySQL实际采用哪个索引来优化对该表的访问。

如果没有使用索引,则该列是NULL。如果想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用force index、ignore index。

(7)key_len列

这一列显示了MySQL在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/e29ab88dd33cafa3b0071b471ee0ab56.html