测试SQL:
explain select
count(1)
from
cms_workflow wf
where
wf.org_id = '149300c4126dc809ee3f7839f4ec03c1'
AND
EXISTS (
select 1
from cms_workflow a left join
cms_workflow_auditor b
on a.apply_id = b.apply_id
where b.auditor_id = '940b22e174d04eef8b4500e5ddc6350c'
and a.apply_id=wf.apply_id
union all
select 1
from cms_workflow a left join
cms_workflow_notice b
on a.apply_id = b.apply_id
where b.notice_user_id = '940b22e174d04eef8b4500e5ddc6350c'
and a.apply_id=wf.apply_id
union all
select 1
from cms_workflow a left join
cms_workflow_todo b
on a.apply_id = b.apply_id
where b.user_id = '940b22e174d04eef8b4500e5ddc6350c'
AND a.apply_id = wf.apply_id
);
查询结果:
id列:数字越大越先执行,如果一样大,就从上往下依次执行,id列为null就表示这是一个结果集,不需要使用他来进行查询
select_type列:
simple:表示不包含union操作或者不包含子查询的简单select查询,有连接查询时,外层的连接查询为simple,且只有一个
primary:一个需要union操作或者含有子查询的select,位于最外层的查询,select_type即为primary,且只有一个
union:union连接的两个select查询,第一个查询是derived派生表,除第一个表外,第二个以后的表select_type都是union
union result:包含union的结果集,在union 和 union result的语句中,因为他不需要参与查询,所以id为null
depent union:与union一样,出现在union或union all 的语句中,但是这个查询要受到外部查询的影响
subquery:除了from子句中包含的子查询外,其他地方出现的子查询都有可能是subquery
depent subquery:与depent union相似,表示这个subquery的查询要受到外部表查询的影响
derived:from子句中出现的子查询,也叫做派生表,其他数据库中可能叫做内联视图或嵌套select
table:显示的查询表名,如果查询使用了别名,那么这里显示的是别名,如果不设计对数据表的操作,那么这显示为null,如果显示为尖括号括起来的<derived N>就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生,如果是尖括号括起来的<union M,N>,与<derived N>类似,也是一个临时表,表示这个结果来自于union查询的id为M,N的结果集
type:
(1)system:表中只有一行数据或者是空表,且只能用于myisam和memory表,如果是Innodbnnodb引擎表,type列在这个情况通常都是all或者index
(2) const:使用唯一索引或者主键,返回记录一定是一行记录的等值where条件,通常type是const,其他数据库也叫做唯一索引扫描
使用唯一索引的执行计划:
不使用唯一索引的执行计划:
(3) eq_ref:出现在要连接多个表的查询计划中,驱动表循环获取数据,这行数据是第二个表的主键或者唯一索引,作为条件查询只返回一条数据,且必须为not null,唯一索引和主键是多列时,只有所有的列都用作比较时才会出现eq_ref
(4) ref: 不像eq_ref那样要求连接顺序,也没有主键和唯一索引的要求,只有使用相等条件检索时就可能出现,常见于辅助索引的等值查找或者多列主键、唯一索引中,使用第一个列之外的列作为等值查找也会出现,总之,返回数据不唯一的等值查找就可能出现
(5) fulltext: 全文索引检索,全文索引的优先级很高,若全文索引和普通索引同时存在时;mysql不管代价,优先使用全文索引
(6) ref_of_null: 与ref方法类似,只是增加了null值得比较,实际用的不多
(7) index_merge:表示查询使用了两个以上的索引,最后取交集或者并集,常见and,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取多个索引,性能可能大部分时间都不如range
(8) index:索引全表扫描 ,把所有从头到尾扫一遍,常见于使用索引列就可以处理不需要读取数据文件的查询,可以使用索引排序或者分组的查询
(9) all:这个就是全表扫描数据文件,然后在server层进行过滤返回符合要求的数据
type列总结:
possible_keys:查询可能使用到的索引
key:查询真正使用到的索引,select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type只会出现一个
key_len:用于处理查询的索引长度,如果是单列索引,那就是整个索引长度,如果是多列索引,那么查询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的列不会计算进去,留意下这个列的值,算一下你的多列索引总长度就知道有么有使用到所有的列了。另外,ken_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中
ref:如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func
extra:
filtered: