MySql 中sql 语句的执行顺序

  1. join中相比where优先推荐on
    WHERE子句中使用的连接语句,在数据库语言中,被称为隐性连接。INNER JOIN……ON子句产生的连接称为显性连接。(其他JOIN参数也是显性连接)WHERE和INNER JOIN产生的连接关系,没有本质区别,结果也一样。但是!隐性连接随着数据库语言的规范和发展,已经逐渐被淘汰,比较新的数据库语言基本上已经抛弃了隐性连接,全部采用显性连接了。

无论怎么连接,都可以用join子句,但是连接同一个表的时候,注意要定义别名,否则产生错误!
参考:http://blog.sina.com.cn/s/blog_54cd1aa30100plmx.html

  1. 逻辑上一个query的执行顺序(不是实际)
    1. FROM
    2. ON
    3. JOIN
    4. WHERE
    5. GROUP BY
    6. WITH CUBE or WITH ROLLUP
    7. HAVING
    8. SELECT
    9. DISTINCT
    10. ORDER BY
    11. TOP

说是“逻辑上” 顺序,因为实际执行时还要看索引,数据分布等,看最终优化器如何处理,最真实的顺序肯定是执行计划展示的顺序。

下面这段参考: http://www.phpddt.com/db/join-on-where.html
引用
SQL语句中join连表时on和where后都可以跟条件,那么对查询结果集,执行顺序,效率是如何呢?
通过查询资料发现:
区别:
on是对中间结果进行筛选,where是对最终结果筛选。

执行顺序:
先进行on的过滤, 而后才进行join。

效率:
如果是inner join, 放on和放where产生的结果一样, 但没说哪个效率速度更高? 如果有outer join (left or right), 就有区别了, 因为on生效在先, 已经提前过滤了一部分数据, 而where生效在后.
最后来了解下T-SQL对查询逻辑处理。
T-SQL逻辑查询的各个阶段(编号代表顺序):
(5)SELECT DISTINCT TOP(<top_specification>) <select_list>
(1)FROM <left_table> <join_type> JOIN <right_table> ON <on_predicate>
(2)WHERE <where_predicate>
(3)GROUP BY <group_by_specification>
(4)HAVING <having_predicate>
(6)ORDER BY <order_by_list>

T-SQL在查询各个阶级分别干了什么:
(1)FROM 阶段
FROM阶段标识出查询的来源表,并处理表运算符。在涉及到联接运算的查询中(各种join),主要有以下几个步骤:
  a.求笛卡尔积。不论是什么类型的联接运算,首先都是执行交叉连接(cross join),求笛卡儿积,生成虚拟表VT1-J1。

  b.ON筛选器。这个阶段对上个步骤生成的VT1-J1进行筛选,根据ON子句中出现的谓词进行筛选,让谓词取值为true的行通过了考验,插入到VT1-J2。 

 c.添加外部行。如果指定了outer join,还需要将VT1-J2中没有找到匹配的行,作为外部行添加到VT1-J2中,生成VT1-J3。 

经过以上步骤,FROM阶段就完成了。概括地讲,FROM阶段就是进行预处理的,根据提供的运算符对语句中提到的各个表进行处理(除了join,还有apply,pivot,unpivot) 

(2)WHERE阶段
WHERE阶段是根据<where_predicate>中条件对VT1中的行进行筛选,让条件成立的行才会插入到VT2中。

(3)GROUP BY阶段
GROUP阶段按照指定的列名列表,将VT2中的行进行分组,生成VT3。最后每个分组只有一行。

(4)HAVING阶段
该阶段根据HAVING子句中出现的谓词对VT3的分组进行筛选,并将符合条件的组插入到VT4中。

(5)SELECT阶段
  这个阶段是投影的过程,处理SELECT子句提到的元素,产生VT5。这个步骤一般按下列顺序进行
a.计算SELECT列表中的表达式,生成VT5-1。
b.若有DISTINCT,则删除VT5-1中的重复行,生成VT5-2
c.若有TOP,则根据ORDER BY子句定义的逻辑顺序,从VT5-2中选择签名指定数量或者百分比的行,生成VT5-3

(6)ORDER BY阶段
根据ORDER BY子句中指定的列明列表,对VT5-3中的行,进行排序,生成游标VC6.

如果是inner join, 放on和放where产生的结果一样, 执行计划也是一样,但推荐使用on。但如果有outer join (left or right), 就有区别了, 因为on生效在先, 已经提前过滤了一部分数据, 而where生效在后,而且where对于outer join有不生效的情况:http://www.cnblogs.com/hgwy/articles/1691689.html

参考:
http://www.phpddt.com/db/join-on-where.html
http://dba.stackexchange.com/questions/5038/sql-server-join-where-processing-order
http://blog.chinaunix.net/uid-27570589-id-3771152.html

这篇http://coolshell.cn/articles/3463.html也提到:
引用
如果不是使用嵌套的select语句,一般系统都会产生笛卡尔乘积然再做过滤。这是对于性能来说是非常危险的,尤其是表很大的时候。

![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/77ad8f8e86aed7c9598f1fe8d6978233.png#pic_center

SQL 语句执行顺序,如下图,共有11个步骤:

在这里插入图片描述

具体的每个阶段:

(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 子句将表中的唯一的值组合成为一组,得到虚拟表VT5。如果应用了group by,那么后面的所有步骤都只能得到的vt5的列或者是聚合函数列,原因在于最终的结果集中只为每个组包含一行
(6) :CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6.
(7) :HAVING: 对虚拟表VT6应用having过滤,只有符合的记录才会被 插入到虚拟表VT7中
(8) :SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中
(9) :DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9(如果应用了group by,那么distinct就是多余的)
(10) :ORDER BY: 将虚拟表VT9中的记录按照<order_by_list>进行排序操作,产生虚拟表VT10
(11) :LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值