`
足至迹留
  • 浏览: 485236 次
  • 性别: Icon_minigender_1
  • 来自: OnePiece
社区版块
存档分类
最新评论

sql基础回顾-2 (join on和where执行顺序)

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

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

2. 逻辑上一个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生效在后,而且on对于outer join有不生效的情况,需要看and条件是作用在左表还是右表: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语句,一般系统都会产生笛卡尔乘积然再做过滤。这是对于性能来说是非常危险的,尤其是表很大的时候。


3. merge join, hash join, nested join
很好的一篇文章:
https://msdn.microsoft.com/zh-cn/library/dn144699.aspx
1
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics