MySQL Explain
Explain 是 MySQL 自带的查询优化器。
使用 Explain + SQL 可查询出执行的相关信息,主要包含以下 10 个属性:
id, select_type, table, type, possible_key, key, key_len, ref, row, filtered, Extra
数据库性能瓶颈,主要关注 CPU 和 IO。
id
反映的是表的读取顺序,或者查询中 SELECT 的执行顺序。
小表永远驱动大表,三种情况:
(1)id 相同,执行顺序是由上至下的
(2)id 不同,如果是子查询,id 序号会递增,id 值越大优先级越高,越先被执行
(3)id 存在相同的,也存在不同的,所有组中,id 越大越先执行,如果 id 相同的,从上往下顺序执行
select_type
反映的是 MySQL 理解的查询类型,有几下几种:
- SIMPLE:简单的 SELECT 查询,查询中不包含子查询或 UNION
- PRIMARY:查询中若包含任何复杂的字部分,最外层查询标记为 PRIMARY
- SUBQUERY:SELECT 或 WHERE 列表中的子查询
- DERIVED:在 FROM 列表中包含的子查询,MySQL 会递归执行这些子查询,把结果放在临时表里
- UNION:若第二个 SELECT 出现在 UNION 后,则被标记为 UNION,若 UNION 包含在 FROM 字句的子查询中,外层 SELECT 将被标记为 DERIVED
- UNION RESULT:UNION 后的结果集
table
反映的是数据从哪张表中读取出来。
例如 <derived2>
表示从 id 为 2 的临时表读取。
type
type 是访问类型排序,反映的是 SQL 的优化状态,有如下几种:
- system:从单表只查出一行记录(等于系统表),这是 const 类型的特例,一般不会出现
- const:查询条件用到了常量,通过索引一次就找到,常在使用 primary key 或 unique 索引中出现
- eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描
- ref:非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问,它可能会找到多个符合条件的行,与eq_ref的差别是eq_ref只匹配了一条记录
- range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引,一般是在where语句中出现了 between、<、>、in 等的查询
- index:full Index scan,index 和 all 的区别为 index 类型只遍历索引树。这通常比 all 快,因为索引文件通常比数据文件小
- all:全表扫描,如果查询数据量很大时,全表扫描效率是很低的
在 SQL 优化中至少做到 range 级别,最好能达到 ref 级别
possible_key & key & key_len
possible_key 反映的是 MySQL 推测可能用到的索引,不一定被查询实际使用到。
key 反映的是实际使用到的索引,若为 null 则是因为没有建索引或者索引失效。
key_len 反映索引中使用的字节数,可计算计算查询中使用的索引的长度,越短越好。其显示的值为索引字段的最大可能长度,而非实际使用长度。
ref
ref 反映的是哪些列或者常量被用于查找索引列上的值。
rows
rows 反映的根据表的统计信息和索引选用的情况,大致估算出来到找到所有记录所需要读取的行数。
filtered
使用 explain extended 时会出现这个列,5.7 之后的版本默认就有这个字段。这个字段表示存储引擎返回的数据在 server 层过滤后,剩下多少满足查询的记录数量的比例,不是具体记录数。
Extra
Extra 反映的不适合在其他列显示,但是也很重要的信息,主要有以下几种:
- Using filesort:MySQL 中无法利用索引完成的排序,这时会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。
- Using temporary:使用了临时表保存中间结果,MySQL 在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。
- Using index:MySQL 相应的 select 操作中使用了覆盖索引,避免了访问表的数据行,效率高。
- Using where:MySQL 使用了 where 过滤。
- Using join buffer:MySQL 使用了连接缓存。
- Impossible where:where 子句的值为 false。
- Distinct:优化 distinct 操作,在找到第一匹配的元组后即停止找同样值的动作。