MySQL索引优化总结(一)
Explain命令
explain用于获取查询相关的执行计划信息,在这个命令中可以知晓查询是如何执行的。
使用explain也很简单,只需要在所需分析的语句前加上explain执行即可。其输出结果如下:
******** 1. row ********
id: 1
select_type: SIMPLE
table: cms_article
type: ref
possible_keys: INDEX_CREATE
key: INDEX_CREATE
key_len: 259
ref: const
rows: 1
Extra: Using index condition
id
这一列用于标识查询编号,如果没有子查询,那么每个索引都会标识为1。
select_type
这行标识了SELECT的类型,即简单查询还是复杂查询
SIMPLE:查询中不包含子查询和UNION查询,即简单查询
对于复杂查询
explain select v.id from (select id from cms_article where create_by = '1') v \G;
explain后会出现多行数据
************ 1. row ***********
id: 1
select_type: PRIMARY
table: <derived2>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 2
Extra: NULL
************ 2. row ************
id: 2
select_type: DERIVED
table: cms_article
type: ref
possible_keys: INDEX_CREATE
key: INDEX_CREATE
key_len: 259
ref: const
rows: 1
Extra: Using where; Using index
最外一层总是PRIMARY。
PRIMARY:表示复杂查询的最外层
DERIVED:用于表示包含在FROM子句中的子查询
UNION:UNION中的第二个或后面的SELECT语句
SUBQUERY:子查询中的SELECT(不在FROM子句中)
table
用于标识查询对应的表,结合id可以看出查询的关联顺序
type
这个属性决定了MySQL如何查找表中的行,也是索引优化的中应该关注的最重要的属性。从差到优,依次为:
all
代表全表扫描,通常是最差的情况
index
按索引次序读取表中数据,最差的情况是按索引的次序读取整个表的数据,这样读取的开销会相当大,因为此时是按照随机的次序去取表中的数据,甚至于比全表扫描效率还低。
range
范围扫描,即有限制的INDEX扫描,通常是带有范围搜索条件时出现。
在通常情况下,优化器会在索引存在的情况下,通过符合 RANGE 范围的条数和总数的比例来选择是使用索引还是进行全表遍历。当需要读取的数据超过一个临界值时,优化器会放弃从索引中读取而改为进行全表扫描,这是为了避免过多的 random disk。
所以有时候会看到使用范围查询时,即使在该字段上建有索引,其type却是ALL的原因。
ref
索引查找,返回的是所有匹配某个单值的行,一般而言在优化得当的SQL查询中,其访问方式多为ref。
eq_ref
和ref类似,只有使用唯一索引或使用主键查找才会出现,其效率比ref更高。
const, system
说明MySQL能将查询转换为常量
NULL
MySQL能在优化阶段分解查询语句,执行阶段甚至不用再访问表或索引。
possible_keys
指出本次查询可以使用哪些索引,这一列是在优化过程早期创建的,有些索引对于后续的优化过程是没用的。
key
显示MySQL实际决定使用的索引。如果没有选择索引,键是NULL。
key_len
显示了MySQL在索引里使用的字节数。
ref
显示使用哪个列(或常数)与key一起从表中选择行。
rows
MySQL估计为了找到所需的行而要读取的行数。这个值虽然不是最终要从表里读取数据的行数,但是也能反映出索引对查询条件的覆盖率。
Extra
这里显示了一些重要的额外信息,对于索引优化工作,首先需要关注以下几个额外信息:
Using index
当在Extra列中显示这个信息时,这表明此次查询没有访问表,因为在索引中已经有足够的数据。所以,可以把这个当作”Using index only”。这里有一点需要注意的是,当使用聚集索引时(通常是主键的默认索引),尽管查询只扫描了索引,但在Extra中并不会显示”Using index”。
Using index condition
当出现这个信息时表明,本次查询首先会访问索引进行搜索过滤,然后从索引中得到结果后再进行回表查询。这里使用了push down技术,具体可以参考官方文档: https://dev.mysql.com/doc/refman/5.6/en/index-condition-pushdown-optimization.html