274_DBA_执行计划_extra
Extra
提示执行计划的一些额外信息
1 No tables used
当查询中没有from子句,会提示该字眼
explain select @@server_uuid
2 Impossible Where
查询语句中where子句用于为false时 提示该信息
explain select * from s1 where 1 < 0
3 No matching min/max row
当查询 有使用 MIN / MAX 聚集函数,单没有记录符合 where子句中的搜索条件时, 将会提示该信息
explain select min(key1) from s1 where key1="alex"
4 Using index
使用 覆盖索引执行查询时,仅通过扫描索引数即可 不需要回表 extra会打印 using index
explain select key1 from s1 where key1 = "alex";
5 Using index condition
有些搜索条件虽然出现了索引列 但不能充当边界条件来形成扫描区间, 就不能用来减少扫描的记录,但MySQL做了优化 index condition pushdown 来减少扫描聚簇索引
explain select key1 from s1 where key1 > "a" and key1 like "%a";
6 Using index condition
有些搜索条件虽然出现了索引列 但不能充当边界条件来形成扫描区间, 就不能用来减少扫描的记录,但MySQL做了优化 index condition pushdown 来减少扫描聚簇索引
explain select key1 from s1 where key1 > "a" and key1 like "%a";
Index condition pushdown 索引下推
虽然 where key1 like “%a” 不能充当边界条件来减少扫描二级索引记录,但是where条件中仅涉及 key1 ; MySQL做了如下优化
- 1 server层调用 innodb接口定位到满足 key1 > “a” 的第一条二级索引记录
- 2 innodb 根据二级索引找到第一条记录后,并不急于回表, 而是判断 key1 like "%a" 是否成立,如果不成立跳过,成立回表取所有数据 返回server
- 3 server层判断其它条件 是否满足
综上: 如果每次扫描到第一条条件就回表 加载数据页,这样耗费性能, 做了不着急回表 在索引B数上判断其它条件,如果满足就回表
索引条件下推特性只是为了在扫描某个扫描区间的二级索引记录时,尽可能减少回表操作次数,减少IO操作,如果对于聚簇索引,不需要回表,起不到减少IO操作
7 Using where
当某个搜索条件需要在server层进行判断,extra列就会提示 using where
explain select * from s1 where key1 = "a" and key3 = "cc";
8 Using join buffer(Block Nested Loop)
当被驱动表不能有效利用索引, mysql会利用 连接缓冲区(join buffer) 内存来加速查询, 也是基于嵌套查询
# using join buffer 对于 被驱动表S2 没用到索引, 使用where 是因为对应s2 where s2.commen_field= 一个常数 需要在server层进行判断
explain select * from s1 join s2 on s1.commen_field = s2.commen_field
9 Using intersect() using union() using sort union()
如果出现了 using intersect() 意味着优化器对索引进行了合并,减少检索范围
explain select * from s2 where key1 = "a" or key3 = "a";
10 Zero limit
当limit 子句参数为0, 表示压根不打算从表中读出任何记录,会提示 zero limit
explain select * from s2 where key1 = "a" or key3 = "a" limit 0;
11 Using filesort Using temporary
对结果集需要进行排序,且无法使用到索引,就需要在内存中 或者 磁盘上利用临时文件对结果集进行排序, 内存/磁盘上排序称为filesort , 如果过程中使用到了临时表 就是using temporary
explain select * from s2 order by s2.commen_field
有时候mysql会利用临时表完成排序,去重,分组等功能, 例 distinct, group by, union 等,且无法有效利用索引,就用内部临时表 会出现using temporary
explain select count(*) commen_field from s2 GROUP BY s2.commen_field
注意
有时候 using filesort 和 using temporary 同时出现, 是因为mysql 默认给 group by 后面添加了 order by 子句; 实际生产中根据实际情况进行设计
explain select count(*) commen_field from s2 GROUP BY s2.commen_field ORDER BY s2.commen_field
IN 转为 半连接 对应的 extra信息
12 Start temporary , end temporary
Start temporary , end temporary
优化器会尝试将in 转成半连接, 当策略为 duplicate_Weedout时(通过创建临时表方式为外层查询中的记录进行去重操作) 驱动表执行计划对应extra为start temporary, 被驱动表为 end temporary
explain select * from s1 where key2 in (SELECT key2 from s2 where s2.commen_field = "alex")
# 其实优化器将SQL 优化成 select * from s1 semi join s2 on s1.key2 = s2.key2 where s2.commen_field = "alex" 将s2 当成了驱动表
13 looseScan
将in 子查询 转成 semi join ,如果采用looseScan (虽然是扫描索引,但只取键值相同的第一条记录去匹配) 则驱动表执行计划 extra 显示looseScan
# 转成semi join select * from s1 semi join s2 on s1.key3= s2.key1 where s2.key1 like “a%”
# 转成semi join 后 s2 作为驱动表; 基于索引 key1检索中结果集符合 s2.key1 like “a%” 可能有 3865条,例 aalex aalex abob abob, 再做代入内层循环时候,只会取第一个 s2.key1 =aalex 作为条件代入 内层循环去判断 是否能在 s1 找到对应的记录,如果能找到就返回结果集,不能找到则进行下一次判断
备注: 只会取键值相同的第一条记录去进行判断
explain select * from s1 where s1.key3 in (SELECT key1 from s2 where s2.key1 like "a%" )
14 FirstMatch(tableName)
首次匹配时最原始的semi join 执行方式, 先去外层查询一条记录, 然后到子查询中寻找服务匹配条件的记录
# s2 是子查询 意味着会被执行多次 且要判断是否符合外层传入的列值
explain select * from s1 where s1.commen_field in (SELECT key1 from s2 where s2.key1 = s1.key1)
- 点赞
- 收藏
- 关注作者
评论(0)