explain 是非常重要的性能查询的工具!!!
1、嵌套查询
首先大家都知道我们一般不提倡嵌套查询或是join查询
原因在哪呢?
下面是一个简单地嵌套查询
SELECT id ,name ,age
FROM teacher
WHERE status=0 and name IN (
SELECT name FROM student WHERE age >18
)
我们一开始设想的是先执行内部查询,然后再执行外部查询的。
这是我们美好的愿景。
这个时候我们就可以使用explain来看一下这条语句的执行过程是怎样的
+------+--------------+-------------+--------+---------------+--------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+--------------+-------------+--------+---------------+--------------+---------+------+------+-------------+
| 1 | PRIMARY | teacher | ALL | NULL | NULL | NULL | NULL |65712| Using where |
| 1 | PRIMARY | <subquery2> | eq_ref | distinct_key | distinct_key | 4 | func | 1 | |
| 2 | DEPENDENT SUBQUERY| student | ALL | NULL | NULL | NULL | NULL | 418 | Using where |
这里可以看到student表的select_type是DEPENDENT SUBQUERY
DEPENDENT SUBQUERY是什么意思呢
翻译就是依靠外层查询
简而言之就是student内层查询要依靠外层查询
如上面显示,teacher表中关联行数是65712
那就意味着内层查询要执行6万次之多,肯定会很慢的。
但也不是所有的嵌套的select_type都是DEPENDENT SUBQUERY
比如还有MATERIALIZED类型,他就是sql自己进行的优化,他会在第一次进行子查询的时候建立一个临时表,保证后续查询的速度。
2、join查询
join连接也是类似的,联表查询时,会有一个驱动表来作为原始数据的循环表。
如果使用的是left join那么左表就是这个驱动表,反之亦然
我们要尽量用小表来当做驱动表。如果实在不能判断哪个比较合适就用join让mysql来帮你做选择,他会自动选择一个小表来做驱动表。
3、解决方法
1、首先,最直接简单地方法就是不使用嵌套查询。
使用多个单个的查询来代替嵌套查询
2、其次,我们还可以使用临时表进行简单地嵌套查询
SELECT id ,name ,age
FROM teacher t, (SELECT name FROM student WHERE age>18) s
WHERE t.status=0 and t.name=s.name
)