Mysql语句的执行顺序

MySQL的语句一共分为11步,如下图所标注的那样,最先执行的总是FROM操作,最后执行的是LIMIT操作。其中每一个操作都会产生一张虚拟的表,这个虚拟的表作为一个处理的输入,只是这些虚拟的表对用户来说是透明的,但是只有最后一个虚拟的表才会被作为结果返回。如果没有在语句中指定某一个子句,那么将会跳过相应的步骤。
这里写图片描述

下面我们来具体分析一下查询处理的每一个阶段:

(1)FORM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1。(选择相对小的表做基础表)

(2)ON: 对虚表VT1进行ON筛选,只有那些符合的行才会被记录在虚表VT2中。

(3)JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, 如果 from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。

(4)WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合的记录才会被插入到虚拟表VT4中。

(5)GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5。

(6)CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6。

(7)HAVING: 对虚拟表VT6应用having过滤,只有符合的记录才会被 插入到虚拟表VT7中。

(8)SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。

(9)DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9.

(10)ORDER BY: 将虚拟表VT9中的记录按照进行排序操作,产生虚拟表VT10.

(11)LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。

有几个问题需要特别留意下:

1)对于包含outer join子句的查询,就有一个让人感到困惑的问题,到底在on筛选器还是用where筛选器指定逻辑表达式呢?

on和where的最大区别在于,如果在on应用逻辑表达式中,那么在第三步outer join中还可以把移除的行再次添加回来,而where的移除后得到的是最终结果。

举个简单的例子,有一个学生表(班级,姓名)和一个成绩表(姓名,成绩),我现在需要返回一个x班级的全体同学的成绩,但是这个班级有几个学生缺考,也就是说在成绩表中没有记录。为了得到我们预期的结果我们就需要在on子句指定学生和成绩表的关系(学生.姓名=成绩.姓名)那么我们是否发现在执行第二步的时候,对于没有参加考试的学生记录就不会出现在vt2中,因为他们被on的逻辑表达式过滤掉了,但是我们用left outer join就可以把左表(学生)中没有参加考试的学生找回来,因为我们想返回的是x班级的所有学生,如果在on中应用学生.班级=’x’的话,left outer join会把所有班级的所有学生记录找回,所以只能在where筛选器中应用学生.班级=’x’ 因为它的过滤是最终的。

2)GROUP BY语句和DISTINCT语句不能同时用在同一个字段上!!!

事实上如果应用了group by子句那么distinct是多余的,原因同样在于,分组的时候是将列中唯一的值分成一组,同时只为每一组返回一行记录,那么所以的记录都将是不相同的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章