两条sql语句
select
t1.*
from
t_alarm_notice_all t1
where
taskId IN
(
select
taskId
from
t_task_user
where
userId = 999
)
order by
t1.latm desc
limit 10
select
t1。*
from
t_alarm_notice_all t1
where
taskId IN
(
'777'
)
order by
t1.latm desc
limit 10
其中 t_task_user
表中只有一条数据就是 userid = 999 taskid = 777
上面的子查询的语句执行需要6秒,而下面的语句只要30毫秒。
explain 分析后发现子查询语句,被驱动表走了全表扫描,建立的 taskid和latm的复合索引失效.
结论
mysql 判断这条sql的流程,子查询里面查询出来的数据可能是一个数组,又有order by 排序.先遍历子查询里面的第一条,获取到值之后,因为有order by
的存在,所以必须排序,但是只拿到第一条数据是排序不了的,只能接着往后取,获取到子查询里面所有数据放到临时表中,再进行排序.这就导致建立的 taskid_latm 索引派不上用场.
而如果写的是常量,则mysql已经知道只有一个值了,就会走索引
只进行了一个回表的扫描,如果in 里面只有一个数
而 IN 里面如果有两个数字,索引的排序功能就失去了,需要用到filesort