系列文章目录
文章目录
- 系列文章目录
- 前言
前言
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。
虽然 MySQL5.6 引入了物化特性,但需要特别注意它目前仅仅针对查询语句的优化。对于更新或删除需要手工重写成 JOIN。
借助 explain 执行计划来分析索引失效的具体场景。看到 SQL 执行计划中select_type字段中出现“DEPENDENT SUBQUERY”时,要特别注意。
来看一个SQL
EXPLAIN SELECT t.id FROM student t WHERE t.is_del=0 and t.classin_err_times<10
AND (SELECT count(*) FROM classin_student ct WHERE ct.stu_id=t.id)<1 ORDER BY t.id DESC;
系统会给学员生成一个信息,生成后会录入到classin_student,这里要查找没有录入该信息的学员,就是ID不在classin_student表中的数据。
看执行计划
DEPENDENT SUBQUERY
在SELECT或WHERE列表中包含了子查询,子查询基于外层
官方含义为:
SUBQUERY:子查询中的第一个SELECT;
DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询 。
MySQL执行逻辑是,先根据is_del和classin_err_times把外层数据查出来,然后根据外层的查询结果,又走了一个子查询,这个子查询的执行依赖于外层结果量。
建议使用JOIN进行优化
EXPLAIN SELECT t.id FROM student t LEFT JOIN classin_student ct ON t.id = ct.stu_id
WHERE t.is_del = 0 AND t.classin_err_times < 10 AND IFNULL(ct.id, 0) = 0;
查看执行计划,成了两个SIMPLE查询。
附录:
DBA观点引用:MySQL 子查询的弱点:mysql 在处理子查询时,会改写子查询。
通常情况下,我们希望由内到外,先完成子查询的结果,然后再用子查询来驱动外查询的表,完成查询。
例如:
select * from test where tid in (select fk_tid from sub_test where gid=10)
通常我们会感性地认为该 sql 的执行顺序是:
sub_test 表中根据 gid 取得 fk_tid(2,3,4,5,6)记录,
然后再到 test 中,带入 tid=2,3,4,5,6,取得查询数据。
但是实际mysql的处理方式为:
select * from test where exists (
select * from sub_test where gid=10 and sub_test.fk_tid=test.tid)
mysql 将会扫描 test 中所有数据,每条数据都将会传到子查询中与 sub_test 关联,子查询不会先被执行,所以如果 test 表很大的话,那么性能上将会出现问题。