转自:https://www.cnblogs.com/xuanzhi201111/p/4175635.html
https://segmentfault.com/a/1190000018729502,https://www.cnblogs.com/stevenchen2016/p/5770214.html
1.例子
EXPLAIN可以解释说明 SELECT, DELETE, INSERT, REPLACE, and UPDATE 等语句. 增删改查都行。
2.输出信息
select_type:查询类型
- SIMPLE:简单表,不使用表连接或子查询;
- PRIMARY : 主查询,外层的查询 (?什么意思?)
- UNION 第二个或者后面的查询语句。(?什么意思?)
- SUBQUERY : 子查询中的第一个select。
partitions:匹配的分区,对于未分区表,该值为空
type:表示MySql在表中找到所需行的方式,或者是访问类型。下面依次性能由最差到最好:
- type=ALL 全表扫描
- type=index 索引全扫描,遍历整个索引来查询匹配的行
- type=range 索引范围扫描,常见于 <,<=,>,>=,between,in等操作符;
- type=ref 使用非唯一索引或唯一索引的前缀扫描,返回匹配某个单独值的记录行;
- type=eq_ref 类似于ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中有一条记录匹配;
- type=const/system 单表中最多有一个匹配行。主要用于比较primary key [主键索引]或者unique[唯一]索引,因为数据都是唯一的,所以性能最优。条件使用=。
- type=NULL 不用访问表或者索引,直接就能够得到结果
possible_keys : 可能使用的索引列表.
key : 实现执行使用索引列表。如果没有就为null,【语句有没有使用到索引主要还是看这个字段】。
key_len : 索引的长度
ref : 显示使用哪个列或常数与key一起从表中选择行(?)
row : 执行查询的行数,简单且重要,数值越大越不好,说明没有用好索引
Extra: 包含MySQL解决查询的详细信息。
https://www.cnblogs.com/kerrycode/p/9909093.html
- Using Index:表示直接访问索引就能够获取到所需要的数据(覆盖索引),不需要通过索引回表;覆盖索引: 如果一个索引包含(或者说覆盖)所有需要查询的字段的值。我们称之为“覆盖索引”。指索引的叶子节点中已经包含要查询的数据【就是说select的列全都命中索引了,已经存储在叶子结点了,就不需要去表里取全部的数据了,所以在写select语句时尽量用到哪些列才写出来,用不到的不要写,select * 不高效】。
- Using where:表示MySQL服务器在存储引擎收到记录后进行“后过滤”(Post-filter),如果查询未能使用索引,Using where的作用只是提醒我们MySQL将用where子句来过滤结果集。一般发生在不能走索引扫描的情况下或者走索引扫描,但是有些查询条件不在索引当中的情况下。
3.查询量大时不走索引
https://blog.csdn.net/wo541075754/article/details/123104860,https://juejin.cn/post/6934886325300494350#comment
比如针对以下两条语句,针对trans_date已建立索引,
EXPLAIN select * from t_trans_log_info where trans_date > '20220222'; EXPLAIN select * from t_trans_log_info where trans_date > '20120222';
第一条会走索引,第二条不会。因为第二条查询量大。
上述索引失效是因为DBMS发现全表扫描比走索引效率更高,因此就放弃了走索引。当Mysql发现通过索引扫描的行记录数超过全表的10%-30%时,优化器可能会放弃走索引,自动变成全表扫描。某些场景下即便强制SQL语句走索引,也同样会失效。
//那从上面的说法来看,通过索引去查询会有回表的过程?一般来说会是这样,只要不是覆盖索引,回表过程是随机IO?不如直接全表扫描顺序IO?