第一章 逻辑查询处理
2016-03-13 18:31
225 查看
执行顺序的不同点
SQL Server与其他编程语言一个显著的不同点就在于处理逻辑的顺序。众所周知,其他的编程语言都是按照编码的顺序进行执行的,但是对于SQL而言,第一个被处理的子句是FROM,而最后一个被处理的则是SELECT子句,尽管他是在语法规范中第一个出现的。
每个步骤都会产生一个虚拟表,这个虚拟表将作为下一个步骤的输入,过程中得到的虚拟表是不可用的,只有最后一个步骤产生的虚拟表才可以被使用。
逻辑查询处理阶段
对于SQL语句的逻辑查询处理过程,可以用下图表示:
![](file:///C:/Users/caosq/AppData/Local/YNote/data/qqBBE0F4309F7DF0FCCC2CC35FF5AD2937/3a81da55ab804d8990221052df3a1d72/clipboard.png)
![](http://images2015.cnblogs.com/blog/490562/201603/490562-20160313182326038-207059337.png)
逻辑查询处理阶段简介
FROM:对FROM子句中的前两个表执行笛卡尔积(Cartesian product)(交叉联接),生成虚拟表VT1
ON:对VT1应用ON筛选器。只有那些使<join_condition>为真的行才被插入VT2。
OUTER(JOIN):如 果指定了OUTER JOIN(相对于CROSS JOIN 或(INNER JOIN),保留表(preserved table:左外部联接把左表标记为保留表,右外部联接把右表标记为保留表,完全外部联接把两个表都标记为保留表)中未找到匹配的行将作为外部行添加到 VT2,生成VT3.如果FROM子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到处理完所有的表为止。
WHERE:对VT3应用WHERE筛选器。只有使<where_condition>为true的行才被插入VT4.
GROUP BY:按GROUP BY子句中的列列表对VT4中的行分组,生成VT5.
CUBE|ROLLUP:把超组(Suppergroups)插入VT5,生成VT6.
HAVING:对VT6应用HAVING筛选器。只有使<having_condition>为true的组才会被插入VT7.
SELECT:处理SELECT列表,产生VT8.
DISTINCT:将重复的行从VT8中移除,产生VT9.
ORDER BY:将VT9中的行按ORDER BY 子句中的列列表排序,生成游标(VC10).
TOP:从VC10的开始处选择指定数量或比例的行,生成表VT11,并返回调用者。
注:
很多人对ON和WHERE条件搞不清楚,觉得把过滤条件放在ON和放在WHERE后面都是一样的。真的一样吗?其实不是的。主要体现在以下两点:
(1)结果不同。我们说WHERE条件是对最终虚拟表的结果做过滤,而ON条件则是对当前虚拟表的结果做筛选,为下一个步骤做准备。直接影响数据的结果记录数。
(2)效率不同。我们知道,sql在表连接的时候,会产生笛卡尔积,不管采用的是INNER JOIN还是OUT LEFT(RIGHT) JOIN,他们都可能会增大数据的虚拟表,这个时候如果我们及时筛选过滤数据,那么相应的产生的虚拟表就会小。但是如果我们都把结果过滤放在WHERE条件上去筛选,那么他产生的虚拟表就可能会非常大。想一下,在10条数据中筛选数据和在10000条数据中筛选数据,哪个处理效率更高,很明显。
有时候我在优化性能的时候,第一步并不是查索引之类的。我第一步都是基于业务对SQL的写法做优化,如果还不行,再考虑其他的。很多时候,我们说查询速度很慢是因为我们的写法出了问题。所以,我一般在写语句的时候,都是能在ON中筛选数据的尽量不写在WHERE中(前提是保证数据的准确性)
三值逻辑
在SQL的逻辑表达式中一共有三种值情况:True,False和Unknown。三值逻辑是SQL语言特有的,SQL中的Unknown通常出现在NULL值的逻辑表达式中。NULL与其他值比较的结果仍然是NULL。
定值逻辑
SQL中有个“同一时间操作”的概念,就是说对于同一个操作语句中,在没有执行完成之前,所有数据都是未被修改的。举例说明:
![](http://images2015.cnblogs.com/blog/490562/201603/490562-20160313182358522-306579138.png)
![](file:///C:/Users/caosq/AppData/Local/YNote/data/qqBBE0F4309F7DF0FCCC2CC35FF5AD2937/c61e9c283a7e4c398b112233a670ae93/clipboard.png)
以上数据是初始数据,下面将对其进行更新操作就可以很明显的看出“定值逻辑”。
![](http://images2015.cnblogs.com/blog/490562/201603/490562-20160313182425632-235583824.png)
SQL Server与其他编程语言一个显著的不同点就在于处理逻辑的顺序。众所周知,其他的编程语言都是按照编码的顺序进行执行的,但是对于SQL而言,第一个被处理的子句是FROM,而最后一个被处理的则是SELECT子句,尽管他是在语法规范中第一个出现的。
每个步骤都会产生一个虚拟表,这个虚拟表将作为下一个步骤的输入,过程中得到的虚拟表是不可用的,只有最后一个步骤产生的虚拟表才可以被使用。
逻辑查询处理阶段
对于SQL语句的逻辑查询处理过程,可以用下图表示:
![](file:///C:/Users/caosq/AppData/Local/YNote/data/qqBBE0F4309F7DF0FCCC2CC35FF5AD2937/3a81da55ab804d8990221052df3a1d72/clipboard.png)
![](http://images2015.cnblogs.com/blog/490562/201603/490562-20160313182326038-207059337.png)
逻辑查询处理阶段简介
FROM:对FROM子句中的前两个表执行笛卡尔积(Cartesian product)(交叉联接),生成虚拟表VT1
ON:对VT1应用ON筛选器。只有那些使<join_condition>为真的行才被插入VT2。
OUTER(JOIN):如 果指定了OUTER JOIN(相对于CROSS JOIN 或(INNER JOIN),保留表(preserved table:左外部联接把左表标记为保留表,右外部联接把右表标记为保留表,完全外部联接把两个表都标记为保留表)中未找到匹配的行将作为外部行添加到 VT2,生成VT3.如果FROM子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到处理完所有的表为止。
WHERE:对VT3应用WHERE筛选器。只有使<where_condition>为true的行才被插入VT4.
GROUP BY:按GROUP BY子句中的列列表对VT4中的行分组,生成VT5.
CUBE|ROLLUP:把超组(Suppergroups)插入VT5,生成VT6.
HAVING:对VT6应用HAVING筛选器。只有使<having_condition>为true的组才会被插入VT7.
SELECT:处理SELECT列表,产生VT8.
DISTINCT:将重复的行从VT8中移除,产生VT9.
ORDER BY:将VT9中的行按ORDER BY 子句中的列列表排序,生成游标(VC10).
TOP:从VC10的开始处选择指定数量或比例的行,生成表VT11,并返回调用者。
注:
很多人对ON和WHERE条件搞不清楚,觉得把过滤条件放在ON和放在WHERE后面都是一样的。真的一样吗?其实不是的。主要体现在以下两点:
(1)结果不同。我们说WHERE条件是对最终虚拟表的结果做过滤,而ON条件则是对当前虚拟表的结果做筛选,为下一个步骤做准备。直接影响数据的结果记录数。
(2)效率不同。我们知道,sql在表连接的时候,会产生笛卡尔积,不管采用的是INNER JOIN还是OUT LEFT(RIGHT) JOIN,他们都可能会增大数据的虚拟表,这个时候如果我们及时筛选过滤数据,那么相应的产生的虚拟表就会小。但是如果我们都把结果过滤放在WHERE条件上去筛选,那么他产生的虚拟表就可能会非常大。想一下,在10条数据中筛选数据和在10000条数据中筛选数据,哪个处理效率更高,很明显。
有时候我在优化性能的时候,第一步并不是查索引之类的。我第一步都是基于业务对SQL的写法做优化,如果还不行,再考虑其他的。很多时候,我们说查询速度很慢是因为我们的写法出了问题。所以,我一般在写语句的时候,都是能在ON中筛选数据的尽量不写在WHERE中(前提是保证数据的准确性)
三值逻辑
在SQL的逻辑表达式中一共有三种值情况:True,False和Unknown。三值逻辑是SQL语言特有的,SQL中的Unknown通常出现在NULL值的逻辑表达式中。NULL与其他值比较的结果仍然是NULL。
定值逻辑
SQL中有个“同一时间操作”的概念,就是说对于同一个操作语句中,在没有执行完成之前,所有数据都是未被修改的。举例说明:
![](http://images2015.cnblogs.com/blog/490562/201603/490562-20160313182358522-306579138.png)
![](file:///C:/Users/caosq/AppData/Local/YNote/data/qqBBE0F4309F7DF0FCCC2CC35FF5AD2937/c61e9c283a7e4c398b112233a670ae93/clipboard.png)
以上数据是初始数据,下面将对其进行更新操作就可以很明显的看出“定值逻辑”。
![](http://images2015.cnblogs.com/blog/490562/201603/490562-20160313182425632-235583824.png)
![](file:///C:/Users/caosq/AppData/Local/YNote/data/qqBBE0F4309F7DF0FCCC2CC35FF5AD2937/b6d4d7eeaa454b70bfecf21222c09034/clipboard.png)
相关文章推荐
- 吝啬的国度 ---用vector 来构图
- HDU 5642 (DP)
- HDU-3183-A Magic Lamp
- 自守数
- spring管理hibernate的SessionFactory-多种配置方法
- UML之状态图
- 文本框和文本视图(NSTextField、NSTextView)
- 线性回归&梯度下降
- javascript中的BOM与DOM、JS核心
- (java) 第二周学习总结
- HTTP stub_status 模块
- PHP Undefined index报错的修复方法
- CentOS 6.7-jdk
- java 文件类File 文本I/O
- java改变png图片的透明度
- IOS中如何切换到主线程工作
- 设计模式_适配器模式
- cocos2dx 手柄
- appium mac 环境搭建
- 数据可视化-工具软件