`

sql 执行顺序

sql 
阅读更多

最近在网上学习到的一些到的知识。

在查询中逻辑查询和物理查询有着本质的区别,SQL不同于其它编程的最明显的特征就是处理代码的顺序,虽然总是最先写SELECT 但是几乎总在最后执行,那到底是怎么一个执行顺序呢 

如下的sql查询语句执行顺序
(1)from
(3) join
(2) on
(4) where
(5)group by
(6) with 
(7)having
(8) select
(9) distinct 
(10) order by
 
    从这个顺序中我们不难发现,所有的 查询语句都是从from开始执行的,在执行过程中,每个步骤都会为下一个步骤生成一个虚拟表,这个虚拟表将作为下一个执行步骤的输入。
第一步:首先对from子句中的前两个表执行一个笛卡尔乘积,此时生成虚拟表 vt1(选择相对小的表做基础表)
第二步:接下来便是应用on筛选器,on 中的逻辑表达式将应用到 vt1 中的各个行,筛选出满足on逻辑表达式的行,生成虚拟表 vt2
第三步:如果是outer join 那么这一步就将添加外部行,left outer jion 就把左表在第二步中过滤的添加进来,如果是right outer join 那么就将右表在第二步中过滤掉的行添加进来,这样生成虚拟表 vt3
第四步:如果 from 子句中的表数目多余两个表,那么就将vt3和第三个表连接从而计算笛卡尔乘积,生成虚拟表,该过程就是一个重复1-3的步骤,最终得到一个新的虚拟表 vt3。
第五步:应用where筛选器,对上一步生产的虚拟表引用where筛选器,生成虚拟表vt4,在这有个比较重要的细节不得不说一下,对于包含outer join子句的查询,就有一个让人感到困惑的问题,到底在on筛选器还是用where筛选器指定逻辑表达式呢?on和where的最大区别在于,如果在on应用逻辑表达式那么在第三步outer join中还可以把移除的行再次添加回来,而where的移除的最终的。举个简单的例子,有一个学生表(班级,姓名)和一个成绩表(姓名,成绩),我现在需要返回一个x班级的全体同学的成绩,但是这个班级有几个学生缺考,也就是说在成绩表中没有记录。为了得到我们预期的结果我们就需要在on子句指定学生和成绩表的关系(学生.姓名=成绩.姓名)那么我们是否发现在执行第二步的时候,对于没有参加考试的学生记录就不会出现在vt2中,因为他们被on的逻辑表达式过滤掉了,但是我们用left outer join就可以把左表(学生)中没有参加考试的学生找回来,因为我们想返回的是x班级的所有学生,如果在on中应用学生.班级='x'的话,那么在left outer join 中就会将不会把x班级的学生的所有记录找回来,所以只能在where筛选器中应用学生.班级='x' 因为它的过滤是最终的。
第六步:group by 子句将中的唯一的值组合成为一组,得到虚拟表vt5。如果应用了group by,那么后面的所有步骤都只能得到的vt5的列或者是聚合函数(count、sum、avg等)。原因在于最终的结果集中只为每个组包含一行。这一点请牢记。
第七步:应用cube或者rollup选项,为vt5生成超组,生成vt6.
第八步:应用having筛选器,生成vt7。having筛选器是第一个也是为唯一一个应用到已分组数据的筛选器。
第九步:处理select列表。将vt7中的在select中出现的列筛选出来。生成vt8.
第十步:应用distinct子句,vt8中移除相同的行,生成vt9。事实上如果应用了group by子句那么distinct是多余的,原因同样在于,分组的时候是将列中唯一的值分成一组,同时只为每一组返回一行记录,那么所以的记录都将是不相同的。
第十一步:应用order by子句。按照order_by_condition排序vt9,此时返回的一个游标,而不是虚拟表。sql是基于集合的理论的,集合不会预先对他的行排序,它只是成员的逻辑集合,成员的顺序是无关紧要的。对表进行排序的查询可以返回一个对象,这个对象包含特定的物理顺序的逻辑组织。这个对象就叫游标。正因为返回值是游标,那么使用order by 子句查询不能应用于表表达式。排序是很需要成本的,除非你必须要排序,否则最好不要指定order by,最后,在这一步中是第一个也是唯一一个可以使用select列表中别名的步骤。
第十二步:应用top选项。此时才返回结果给请求者即用户。
 
SQL where 条件顺序对性能的影响有哪些 
 
经常有人问到oracle中的Where子句的条件书写顺序是否对SQL性能有影响,我的直觉是没有影响,因为如果这个顺序有影响,Oracle应该早就能够做到自动优化,但一直没有关于这方面的确凿证据。在网上查到的文章,一般认为在RBO优化器模式下无影响(10G开始,缺省为RBO优化器模式),而在CBO优化器模式下有影响,主要有两种观点:
  a.能使结果最少的条件放在最右边,SQL执行是按从右到左进行结果集的筛选的;
  b.有人试验表明,能使结果最少的条件放在最左边,SQL性能更高。
  查过oracle8到11G的在线文档,关于SQL优化相关章节,没有任何文档说过where子句中的条件对SQL性能有影响,到底哪种观点是对的,没有一种确切的结论,只好自己来做实验证明。结果表明,SQL条件的执行是从右到左的,但条件的顺序对SQL性能没有影响。
  实验一:证明了SQL的语法分析是从右到左的
  下面的试验在9i和10G都可以得到相同的结果: 第1条语句执行不会出错,第2条语句会提示除数不能为零。
 
 1.Select 'ok' From Dual Where 1 / 0 = 1 And 1 = 2;
 2.Select 'ok' From Dual Where 1 = 2 And 1 / 0 = 1;
 
  证明了SQL的语法分析是从右到左的。
  实验二:证明了SQL条件的执行是从右到左的
 
drop table temp;
create table temp( t1 varchar2(10),t2 varchar2(10));
insert into temp values('zm','abcde');
insert into temp values('sz','1');
insert into temp values('sz','2');
commit;
1. select * from temp where to_number(t2)>1 and t1='sz';
2. select * from temp where t1='sz' and to_number(t2)>1;
 
 
  在9i上执行, 第1条语句执行不会出错,第2条语句会提示“无效的数字”
  在10G上执行,两条语句都不会出错。
  说明:9i上,SQL条件的执行确实是从右到左的,但是10G做了什么调整呢?
  实验三:证明了在10g上SQL条件的执行是从右到左的
 
Create Or Replace Function F1(v_In Varchar2) Return Varchar2 Is
Begin
Dbms_Output.Put_Line('exec F1');
Return v_In;
End F1;
/
Create Or Replace Function F2(v_In Varchar2) Return Varchar2 Is
Begin
Dbms_Output.Put_Line('exec F2');
Return v_In;
End F2;
/
SQL> set serverout on;
SQL> select 1 from dual where f1('1')='1' and f2('1')='1';
1
----------
1
exec F2
exec F1
SQL> select 1 from dual where f2('1')='1' and f1('1')='1';
1
----------
1
exec F1
exec F2
 
 
  结果表明,SQL条件的执行顺序是从右到左的。
  那么,根据这个结果来分析,把能使结果最少的条件放在最右边,是否会减少其它条件执行时所用的记录数量,从而提高性能呢?
  例如:下面的SQL条件,是否应该调整SQL条件的顺序呢?
 
Where A.结帐id Is Not Null
And A.记录状态<>0
And A.记帐费用=1
And (Nvl(A.实收金额, 0)<>Nvl(A.结帐金额, 0) Or Nvl(A.结帐金额, 0)=0)
And A.病人ID=[1] And Instr([2],','||Nvl(A.主页ID,0)||',')>0
And A.登记时间Between [3] And [4]
And A.门诊标志<>1
 
 
  实际上,从这条SQL语句的执行计划来分析,Oracle首先会找出条件中使用索引或表间连接的条件,以此来过滤数据集,然后对这些结果数据块所涉及的记录逐一检查是否符合所有条件,所以条件顺序对性能几乎没有影响。
        如果没有索引和表间连接的情况,条件的顺序是否对性能有影响呢?再来看一个实验。
  实验四:证明了条件的顺序对性能没有影响。
 
SQL> select count(*) from诊疗项目目录where操作类型='1';
COUNT(*)
----------
3251
SQL> select count(*) from诊疗项目目录where类别='Z';
COUNT(*)
----------
170
SQL> select count(*) from诊疗项目目录where类别='Z' and操作类型='1';
COUNT(*)
----------
1
Declare
V1 Varchar2(20);
Begin
For I In 1 .. 1000 Loop
--Select名称Into V1 From诊疗项目目录Where类别= 'Z' And操作类型= '1';
select名称Into V1 from诊疗项目目录where操作类型='1' and类别='Z';
End Loop;
End;
/
 
 
  上面的SQL按两种方式分别执行了1000次查询,结果如下:
  操作类型= '1'在最右|类别='Z'在最右
  
    0.093                            |      1.014
  1.06                             |      0.999
  0.998                            |      1.014
 
  按理说,从右到左的顺序执行,“类别='Z'”在最右边时,先过滤得到170条记录,再从中找符合“操作类型 = '1'”的,比较而言,“操作类型 = '1'”在最右边时,先过滤得到3251条记录,再从中找符合“类别='Z'”,效率应该要低些,而实际结果却是两者所共的时间差不多。
  其实,从Oracle的数据访问原理来分析,两种顺序的写法,执行计划都是一样的,都是全表扫描,都要依次访问该表的所有数据块,对每一个数据块中的行,逐一检查是否同时符合两个条件。所以,就不存在先过滤出多少条数据的问题。
  综上所述,Where子句中条件的顺序对性能没有影响(不管是CBO还是RBO优化器模式),注意,额外说一下,这里只是说条件的顺序,不包含表的顺序。在RBO优化器模式下,表应按结果记录数从大到小的顺序从左到右来排列,因为表间连接时,最右边的表会被放到嵌套循环的最外层。最外层的循环次数越少,效率越高。
 
分享到:
评论

相关推荐

    SQL执行顺序

    SQL执行顺序介绍

    SQL执行过程和优化

    oracle SQL执行过程和优化 索引分类 索引注意事项 执行过程

    sql语句的顺序是怎么执行的

    Sql语句执行顺序Sql语句执行顺序Sql语句执行顺序Sql语句执行顺序Sql语句执行顺序Sql语句执行顺序Sql语句执行顺序

    oracle sql执行过程(流程图)

    Oracle sql执行流程图_SQL执行过程一、sql语句的执行步骤:1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义。2) 语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限。3)...

    SQL语句执行过程详解

    SQL语句执行过程是一个涉及到客户端与服务器端交互、多个阶段的复杂过程,包含了对SQL语句的处理、解析、优化以及最终的执行。这个过程对于数据库管理员来说,需要对数据库内部结构有深入的了解,才能够完全掌握。 ...

    sql执行过程.zip

    SQL执行过程是数据库管理系统中一个核心且至关重要的环节,它涉及到数据查询、处理与存储的整个生命周期。在MySQL这样的关系型数据库中,SQL语句的执行步骤可以分为多个阶段,让我们详细探讨一下。 首先,当你在...

    使用sql server Profiler监听应用程序执行的sql

    Sql Server Profiler 是 DBA 进行 SQL 监控和调优时必用的工具,对于开发人员来说,能够监控到程序运行时的 SQL,对于排障已经相当方便了。下面将详细介绍如何使用 Sql Server Profiler 监听应用程序执行的 SQL。 ...

    SQL语句执行顺序说明

    ### SQL语句执行顺序说明 #### 一、SQL语句准备执行阶段 当SQL语句进入Oracle的库缓存后,为了确保其...通过遵循上述步骤和技巧,可以有效地提高SQL语句在Oracle数据库中的执行效率,从而提升应用程序的整体性能。

    SQL Server中存储过程比直接运行SQL语句慢的原因

    SQL Server 中存储过程比直接运行 SQL 语句慢的原因 在 SQL Server 中,存储过程比直接运行 SQL 语句慢的原因是 Parameter sniffing 问题。Parameter sniffing 是指 SQL Server 在执行存储过程时,使用参数的统计...

    pl sql批量执行多个sql文件和存储过程

    对于Oracle数据库而言,PL/SQL是一种非常强大的工具,它不仅可以用于编写复杂的数据库应用程序,还能够方便地进行SQL脚本的批量执行以及存储过程的调用。本文将详细介绍如何使用PL/SQL Developer来实现这一功能。 #...

    SQLServer脚本批量执行工具

    在数据库维护或更新过程中,经常需要运行一系列SQL命令来创建表、索引、视图、存储过程等,或者执行数据迁移和更新操作。手动逐一执行这些脚本不仅耗时,还容易出错。通过使用批量执行工具,我们可以将这些脚本整合...

    存储过程中怎么动态执行sql语句

    “存储过程中怎么动态执行SQL语句”这一标题表明文章将介绍如何在Oracle数据库的存储过程中编写能够动态执行的SQL语句。动态SQL是指在运行时才能确定其具体内容的SQL语句,它允许用户根据不同的条件构造不同的查询或...

    SQL查询原理及执行顺序

    本文将深入探讨SQL查询的执行过程,帮助读者理解如何构建高效查询。 #### SQL语句执行步骤 SQL查询的执行流程可以分为以下九个主要阶段: 1. **语法分析**:此阶段,数据库引擎检查SQL语句的语法正确性,确保其...

    Oracle 共享池和数据库高速缓冲区,引出SQL执行过程.pdf

    Oracle 共享池和数据库高速缓冲区,引出SQL执行过程

    sql执行过程_原理_优化

    oracle sql语句的执行过程和原理介绍,优化器模式,访问table的方式,表的连接方式及索引分类

    SQL脚本批量执行,方便大量的SQL脚本执行。

    5. **存储过程**:在某些情况下,可以创建一个存储过程来执行传入的动态SQL,然后通过调用这个存储过程批量处理脚本。 6. **自动化工具**:市面上还有一些专门的数据库管理工具,如Redgate SQL Toolbelt,提供了...

    自动执行SQL语句&创建标准的Sql 存储过程

    首先,自动执行SQL语句是指通过一定的机制,让预定义的SQL命令在特定时间或触发事件时自动运行。这通常涉及到数据库的定时任务、事件调度器或者应用程序的后台进程。例如,在MySQL中,我们可以使用事件调度器来创建...

    SQLServer存储过程调用WebService

    3. **执行存储过程**:最后,通过调用此存储过程来发起 Web Service 的调用请求。 **创建存储过程示例**: ```sql CREATE PROCEDURE dbo.CallWebService @Url NVARCHAR(500), @MethodName NVARCHAR(100) AS ...

    通过分析SQL语句的执行计划优化SQL.doc

    Row Source则表示SQL执行过程中的数据源,它可以是表、视图、索引或者其他数据源。理解Row Source对于分析SQL执行路径至关重要。Driving Table是查询中驱动整个连接操作的表,它的选择直接影响到查询效率。Probed ...

Global site tag (gtag.js) - Google Analytics