5)SUBQUERY:包含在 select 中的子查询(不在 from 子句中),不依赖于外部查询的结果集
1 2 3 4 5 6 7
explain select*from employees where id in (select id from employees2) or name ='a' +----+-------------+------------+------------+-------+-----------------------+-----------------------+---------+--------+-------+----------+-------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+------------+------------+-------+-----------------------+-----------------------+---------+--------+-------+----------+-------------+ |1|PRIMARY| employees |<null>|ALL| idx_name_age_position |<null>|<null>|<null>|92796|100.0|Usingwhere| |2| SUBQUERY | employees2 |<null>| index |PRIMARY| idx_name_age_position |140|<null>|10|100.0|Using index | +----+-------------+------------+------------+-------+-----------------------+-----------------------+---------+--------+-------+----------+-------------+
explain select*from employees where id in (select id from employees2 where name ='a'unionselect id from employees where age =20) +--------+--------------------+------------+------------+--------+-------------------------------+---------+---------+--------+--------+----------+-----------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +--------+--------------------+------------+------------+--------+-------------------------------+---------+---------+--------+--------+----------+-----------------+ |1|PRIMARY| employees |<null>|ALL|<null>|<null>|<null>|<null>|92796|100.0|Usingwhere| |2| DEPENDENT SUBQUERY | employees2 |<null>| eq_ref |PRIMARY,idx_name_age_position |PRIMARY|4| func |1|10.0|Usingwhere| |3| DEPENDENT UNION| employees |<null>| eq_ref |PRIMARY,idx_name_age_position |PRIMARY|4| func |1|10.0|Usingwhere| |<null>|UNIONRESULT|<union2,3>|<null>|ALL|<null>|<null>|<null>|<null>|<null>|<null>|Using temporary | +--------+--------------------+------------+------------+--------+-------------------------------+---------+---------+--------+--------+----------+-----------------+
8)DERIVED:包含在 from 子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表(derived的英文含义)
1 2 3 4 5 6 7
explain select*from (select age,count(*) countNum from employees groupby age) tmp where countNum >3 +----+-------------+------------+------------+-------+-----------------------+-----------------------+---------+--------+-------+----------+------------------------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+------------+------------+-------+-----------------------+-----------------------+---------+--------+-------+----------+------------------------------+ |1|PRIMARY|<derived2>|<null>|ALL|<null>|<null>|<null>|<null>|92796|100.0|<null>| |2| DERIVED | employees |<null>| index | idx_name_age_position | idx_name_age_position |140|<null>|92796|100.0|Using index; Using temporary | +----+-------------+------------+------------+-------+-----------------------+-----------------------+---------+--------+-------+----------+------------------------------+
explain select name,position from employees where age =20 +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+--------+-------+----------+--------------------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+--------+-------+----------+--------------------------+ |1| SIMPLE | employees |<null>| index | idx_name_age_position | idx_name_age_position |140|<null>|92796|10.0|Usingwhere; Using index | +----+-------------+-----------+------------+-------+-----------------------+-----------------------+---------+--------+-------+----------+--------------------------+
ALL: 即全表扫描,扫描你的聚簇索引的所有叶子节点。
1 2 3 4 5 6
explain select*from employees +----+-------------+-----------+------------+------+---------------+--------+---------+--------+-------+----------+--------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-----------+------------+------+---------------+--------+---------+--------+-------+----------+--------+ |1| SIMPLE | employees |<null>|ALL|<null>|<null>|<null>|<null>|92796|100.0|<null>| +----+-------------+-----------+------------+------+---------------+--------+---------+--------+-------+----------+--------+
其它不常出现的也做简单说明
fulltext: 全文索引,不推荐使用
ref_or_null: 不仅想找出某个二级索引列的值等于某个常数的记录,还想把该列的值为NULL的记录也找出来,如WHERE order_no= 'abc' OR order_no IS NULL;
# 基于主键索引扫描的rows是46398,此时filtered=100,因为没有其它查询条件,此时表示过滤的记录占比总的扫描rows是100% explain select*from employees where id >10 +----+-------------+-----------+------------+-------+---------------+---------+---------+--------+-------+----------+-------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-----------+------------+-------+---------------+---------+---------+--------+-------+----------+-------------+ |1| SIMPLE | employees |<null>|range|PRIMARY|PRIMARY|4|<null>|46398|100.0|Usingwhere| +----+-------------+-----------+------------+-------+---------------+---------+---------+--------+-------+----------+-------------+
# 如果在加一个条件 age =20,此时表示该过滤条件占比 rows 的百分比是 10% explain select*from employees where id >10and age =20 +----+-------------+-----------+------------+-------+---------------+---------+---------+--------+-------+----------+-------------+ | id | select_type |table| partitions | type | possible_keys | key | key_len |ref|rows| filtered | Extra | +----+-------------+-----------+------------+-------+---------------+---------+---------+--------+-------+----------+-------------+ |1| SIMPLE | employees |<null>|range|PRIMARY|PRIMARY|4|<null>|46398|10.0|Usingwhere| +----+-------------+-----------+------------+-------+---------------+---------+---------+--------+-------+----------+-------------+
Extra
Extra列展示的是额外信息,常见信息如下:
1)Using index:使用覆盖索引,索引排序
2)Using where:使用 where 语句来处理结果,并且查询的列未被索引覆盖,出现Using where 只是表示 MySQL 使用 where 子句中的条件对记录进行了过滤,并不表示当前sql没有使用索引,也不表示一定使用全表扫描
3)Using index condition:查询的列不完全被索引覆盖,where条件中是一个前导列的范围
4)Using temporary:mysql需要创建一张临时表来处理查询,比如去重、排序、分组、Union之类的,需要使用索引优化
5)Using filesort:将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序,需要使用索引优化
6)Select tables optimized away:使用某些聚合函数(比如 max、min)来访问存在索引的某个字段
mysql8.0以前的版本需要explain extended select * from actor where id = 1;
1 2 3 4 5 6 7 8 9
mysql> explain select*from actor where id =1; # 显示优化后的sql mysql>show warnings; +-------+------+-----------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+-----------------------------------------------------------------------------------------------------------------------+ | Note |1003|/* select#1 */select'1'AS `id`,'a'AS `name`,'2017-12-22 15:27:18'AS `update_time` from `test`.`actor` wheretrue| +-------+------+-----------------------------------------------------------------------------------------------------------------------+ 1rowinset (0.00 sec)
关联查询inner join之显式连接 VS 隐式连接,从执行计划上看两者是一回事,推荐带on的显示查询
1 2 3 4 5 6 7
# 显式连接1 select*from film_actor innerjoin film on film_actor.film_id = film.id; # 显式连接2,有on会先执行on的关联,之后在进行where过滤,推荐关联关系放到on里面 select*from film_actor innerjoin film where film_actor.film_id = film.id;
# 隐式链接 select*from film_actor,film where film_actor.film_id = film.id;