【2017年整理】SQL查询执行顺序

上传人:爱****1 文档编号:992765 上传时间:2017-05-24 格式:DOC 页数:4 大小:38.50KB
返回 下载 相关 举报
【2017年整理】SQL查询执行顺序_第1页
第1页 / 共4页
【2017年整理】SQL查询执行顺序_第2页
第2页 / 共4页
【2017年整理】SQL查询执行顺序_第3页
第3页 / 共4页
【2017年整理】SQL查询执行顺序_第4页
第4页 / 共4页
亲,该文档总共4页,全部预览完了,如果喜欢就下载吧!
资源描述

《【2017年整理】SQL查询执行顺序》由会员分享,可在线阅读,更多相关《【2017年整理】SQL查询执行顺序(4页珍藏版)》请在金锄头文库上搜索。

1、T-SQL 查询处理执行顺序(一)对于 T-SQL 编程,用得最广泛的,莫过于查询(Querying)。要想写出高质量、高性能的查询语句,必须深入地了解逻辑查询处理。一、逻辑查询处理的各个阶段(5)SELECT DISTINCT TOP() (1)FROM JOIN ON (2)WHERE (3)GROUP BY (4)HAVING (6)ORDER BY 上边语句是一个普通格式的查询语句,基本包含了所有的查询条件和关键字。你可能会发现前边的序号并不是按顺序来的,被你说对了,这是 SQL 与其他编程语言不同的最明显特征,就是它的执行顺序并不是按照编写顺序来的。上边的序号,就是查询语句在执行过程

2、中的逻辑处理顺序。下面简单介绍一下各个阶段都干了啥事。(1)FROM 阶段FROM 阶段标识出查询的来源表,并处理表运算符。在涉及到联接运算的查询中(各种join),主要有以下几个步骤:a. 求笛卡尔积。不论是什么类型的联接运算,首先都是执行交叉连接(cross join),求笛卡儿积,生成虚拟表 VT1-J1。b.ON 筛选器。这个阶段对上个步骤生成的 VT1-J1 进行筛选,根据 ON 子句中出现的谓词进行筛选,让谓词取值为 true 的行通过了考验,插入到 VT1-J2。c.添加外部行。如果指定了 outer join,还需要将 VT1-J2 中没有找到匹配的行,作为外部行添加到 VT1

3、-J2 中,生成 VT1-J3。经过以上步骤, FROM 阶段就完成了。概括地讲,FROM 阶段就是进行预处理的,根据提供的运算符对语句中提到的各个表进行处理(除了 join,还有 apply,pivot ,unpivot )(2)WHERE 阶段WHERE 阶段是根据中条件对 VT1 中的行进行筛选,让条件成立的行才会插入到 VT2 中。(3)GROUP BY 阶段GROUP 阶段按照指定的列名列表,将 VT2 中的行进行分组,生成 VT3。最后每个分组只有一行。(4)HAVING 阶段该阶段根据 HAVING 子句中出现的谓词对 VT3 的分组进行筛选,并将符合条件的组插入到 VT4 中。

4、(5)SELECT 阶段这个阶段是投影的过程,处理 SELECT 子句提到的元素,产生 VT5。这个步骤一般按下列顺序进行a.计算 SELECT 列表中的表达式,生成 VT5-1。b.若有 DISTINCT,则删除 VT5-1 中的重复行,生成 VT5-2c.若有 TOP,则根据 ORDER BY 子句定义的逻辑顺序,从 VT5-2 中选择签名指定数量或者百分比的行,生成 VT5-3(6)ORDER BY 阶段根据 ORDER BY 子句中指定的列明列表,对 VT5-3 中的行,进行排序,生成游标 VC6.当然 SQL SERVER 在实际的查询过程中,有查询优化器来生成实际的工作计划。以何种

5、顺序来访问表,使用什么方法和索引,应用哪种联接方法,都是由查询优化器来决定的。优化器一般会生成多个工作计划,从中选择开销最小的那个去执行。逻辑查询处理都有非常特定的顺序,但是优化器常常会走捷径。Tsql 查询执行顺序(二) T-SQL 查询处理这种逻辑处理顺序,是理论上的处理过程,实际情况还会根据查询优化器选择最优的执行计划。还是从 FROM 阶段讲开。(1)FROM 阶段这个阶段是查询逻辑处理的第一步。想到这里,想起了 LINQ 表达式不就是从 FROM 开始的嘛,看来还是挺有道理的。FROM 阶段负责表示表或要查询的表。如果指定了表运算符,还需 要按从左到右的顺序,对运算符进行逐个处理。表

6、运算符有 4 类,JOIN,APPLY,PIVOT,UNPIVOT。每个表运算符都有自己的处理规则。这里挑最常见的 JOIN来说。对于联接(join),一般有以下几个个步骤:a.求笛卡尔积,对两张表进行 cross join,得出最大的可能结果集。如果左表有 n 行,右表有 m 行,则结果集有 nxm 行。b.利用 ON 筛选条件来筛选,剔除不符合条件的行。c.对于外联接(left,right,full outer join),还需要添加外部行。在上个步骤中,ON 条件剔除掉了所有不匹配两张表的行。但是在外联接中,通过指定外连接的类型,需要将其中的一个或者两个表标记为保留表,并返回该表中所有的

7、行。所以这时候还需要将保留表中被 ON 筛选条件剔除的行重新加入到结果集中(这些重新加进来的表,书中称为外部行),并将外部行中非保留表的列值标记为 NULL.再次提醒一下,这一个步骤,只有外联接才执行,对于内联接(inner join)只需要执行 a 和 b 两个步骤的。(2)WHERE 阶段对于上一步骤返回的虚拟表,经过 where 条件的判定,只有让 where 条件为 true 的行才会被保留下来。请注意,因为还没有对数据进行分组,所以在 where 子句中不能聚合。也不能引用 select 列表中创建的别名,因为 SELECT 阶段还在后头呢。例如 where orderidmax(o

8、rderid), select year(thedate) as theyear. where theyear2010 是不能使用的。另外一个很让人迷惑的问题是,对于包含 JOIN 的查询,到底 ON 和 WHERE 子句有什么区别,应该什么时候使用 ON 子句,什么时候使用 where 子句。这里作一下说明。只有对于外联接,ON 和 where 子句才会存在这种逻辑区别,因为在外联接中,通过 ON 子句的筛选之后,还要对保留表进行外部行添加,而 where 子句则是在外部行添加过之后才进行筛选的。因此,ON 子句对这种外联接的情况的筛选,并不是最终的结果,在 FROM 阶段的第三个步骤,还会

9、把外部行添加回来的。而对于内联接,where 子句和 on 子句作用是完全一样的,在哪里筛选都是同种效果,没有其他步骤。所以在处理这种含有外联接的查询,一定要注意 ON 筛选和 where 筛选的区别,避免使用错了,达不到筛选的效果。另外,对于内联接,一个不错的建议是,对于两个表都存在的字段筛选,用 ON 子句,对于单个表的字段筛选,用 where,例如:select * from a inner join b on a.col = b.col where a.col2 1。(3)GROUP BY 阶段在这一阶段将上一步返回的虚拟表中的结果集按分组进行重组,由分组集所有列的每个唯一组合,标识出

10、一个组。再用这些组,跟上一步返回的每一个行进行关系。注意,每个行只能关联一个组。最后,生成的结果集中,每个组只能有一行。关于 GROUP BY 还有很多有意思的地方,比如 cube,rollup,grouping 等等,有时间再一一介绍。(4)HAVING 阶段HAVING 筛选器用于对上一步返回的结果集进行筛选。HAVING 筛选器是唯一能筛选分组数据的筛选器,ON 和 where 都不行。理由很简单,ON 和 where 都是在分组之前进行处理的,自然不能对分组进行筛选。所以 HAVING 和 WHERE 的区别,也是很显而易见了。HAVING 只能与 SELECT 语句一起使用。HAVI

11、NG 通常在 GROUP BY 子句中使用。如果不使用 GROUP BY 子句,则 HAVING 的行为与 WHERE 子句一样。(5)SELECT 阶段这一个步骤,将构造最终返回给调用者的表。这个步骤涉及到 3 个子阶段。a.计算表达式。在这个阶段中,select 列表可以返回油上一步得到的虚拟表的基础列,也可以是对这些基础列的操作。有一点需要注意的是,在这个 select 列表中,所有的表达式是同时计算的。举个例子,在 SQL 中,可以这么交换两个列值:update tab_test set col1 = col2,col2 =col1;在别的语言看来这的确很神奇。而且在 select 列

12、表中创建的别名不能在同一 select 列表中的其他表达式中使用。所以,基于这个特性,我们就会得出一个结论,select 列表的顺序是无关紧要的。b.处理 DINSTINCT,如果查询中指定了 DINSTINCT,则从上一步返回的虚拟表中删除重复的行。c.应用 TOP 选项。对于指定了 TOP 选项的查询,则会根据查询的 order by 子句来选择指定数量的行。TOP 选项里有很多特殊的地方,此处先不扯远,以后有机会单独讲。(6)ORDER BY 阶段这一步按照 order by 列表中的列明对上一步的表进行排序,返回游标。这里有必要谈一下集合和游标。SQL 的理论基础是集合,集合是无序的,

13、它只是成员的一种逻辑集合。对于带有排序作用的 ORDER BY 子句的查询,可以返回一个对象,其中的行按照特定的顺序组织在一起。ANSI 把这种 对象成为游标(cursor)。因为在这一步中,最后返回的是游标,所以带有 order by 的查询,是不能用来定义视图,子查询,公用表等。例如:SELECT * FROM (SELECT col1,col2 FROM tab_test ORDER BY col1)是无效的,并且将报错。但是如果同时指定了 TOP 选项,则是一个例外。SELECT * FROM (SELECT top (10) col1,col2 FROM tab_test ORDER BY col1),对于这个查询,因为同时指定了 top 和 order by,则子查询中的结果一定是固定而且有序的的,但是外部的查询,则不能保证是有序排列的。对于 T-SQL 查询逻辑处理,就整理到这里,有什么问题,还请大家指出,一起探讨。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号