sql执行顺序和原理

时间:2024.4.25

一、sql语句的执行步骤: 
1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义。 
2) 语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限。 
3)视图转换,将涉及视图的查询语句转换为相应的对基表查询语句。 
4)表达式转换, 将复杂的 SQL 表达式转换为较简单的等效连接表达式。 
5)选择优化器,不同的优化器一般产生不同的“执行计划” 
6)选择连接方式, ORACLE 有三种连接方式,对多表连接 ORACLE 可选择适当的连接方式。 
7)选择连接顺序, 对多表连接 ORACLE 选择哪一对表先连接,选择这两表中哪个表做为源数据表。 
8)选择数据的搜索路径,根据以上条件选择合适的数据搜索路径,如是选用全表搜索还是利用索引或是其他的方式。 
9)运行“执行计划” 
二、oracle 共享原理: 
ORACLE将执行过的SQL语句存放在内存的共享池(shared buffer pool)中,可以被所有的数据库用户共享 当你执行一个SQL语句(有时被称为一个游标)时,如果它和之前的执行过的语句完全相同, ORACLE就能很快获得已经被解析的语句以及最好的 执行路径. 这个功能大大地提高了SQL的执行性能并节省了内存的使用 
三、oracle 语句提高查询效率的方法:1: wherecolumnin(select*from ... where ...); 2:... whereexists (select'X'from ...where ...); 第二种格式要远比第一种格式的效率高。在Oracle中可以几乎将所有的IN操作符子查询改写为使用EXISTS的子查询 使用EXIST,Oracle系统会首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间 Oracle系统在执行IN子查询时,首先执行子查询,并将获得的结果列表存放在在一个加了索引的临时表中 避免使用having字句 避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销 

SQL Select语句完整的执行顺序: 

1、from子句组装来自不同数据源的数据; 
2、where子句基于指定的条件对记录行进行筛选; 
3、group by子句将数据划分为多个分组; 
4、使用聚集函数进行计算; 
5、使用having子句筛选分组; 
6、计算所有的表达式; 
7、使用order by对结果集进行排序 
逻辑查询处理步骤 
代码如下: 

Java代码  

1.  (8)SELECT (9)DISTINCT   

2.  (11)<TOP_specification> <select_list>   

3.  (1)FROM <left_table>   

4.  (3)<join_type> JOIN <right_table>   

5.  (2)    ON <join_condition>   

6.  (4)WHERE <where_condition>   

7.  (5)GROUP BY <group_by_list>   

8.  (6)WITH {CUBE ROLLUP}   

9.  (7)HAVING <having_condition>   

10.(10)ORDER BY <order_by_list>   



每个步骤产生一个虚拟表,该虚拟表被用作下一个步骤的输入。只有最后一步生成的表返回给调用者。如 
果没有某一子句,则跳过相应的步骤。 
1. FROM:对FROM子句中的前两个表执行笛卡尔积,生成虚拟表VT1。 
2. ON:对VT1应用ON筛选器。只有那些使<join_condition>为真的行才被插入VT2。 
3. OUTER(JOIN):如果指定了OUTER JOIN,保留表中未找到匹配的行将作为外部行添加到VT2,生成VT3。 
如果FROM子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到 
处理完所有的表为止。 
4. 对VT3应用WHERE筛选器。只有使<where_condition>为TRUE的行才被插入VT4。 
5. GROUP BY:按GROUP BY 子句中的列列表对VT4中的行分组,生成VT5。 
6. CUBEROLLUP:把超组插入VT5,生成VT6。 
7. HAVING:对VT6应用HAVING筛选器。只有使<having_condition>为TRUE的组才会被插入VT7。 
8. SELECT:处理SELECT列表,产生VT8。 
9. DISTINCT:将重复的行从VT8中移除,产生VT9。 
10. ORDER BY:将VT9中的行按ORDER BY子句中的列列表排序,生成一个有表(VC10)。 
11. TOP:从VC10的开始处选择指定数量或比例的行,生成表VT11,并返回给调用者。 
以下是其它网友的补充: 
好像自已在书写 SQL 语句时由于不清楚各个关键字的执行顺序, 往往组织的 SQL 语句缺少很好的逻辑, 凭感觉 "拼凑" ( 不好意思, 如果您的 SQL 语句也经常 "拼凑", 那您是不是得好好反省一下呢?, 呵呵). 
这样做确实是爽了自己, 可苦了机器, 服务器还需要在我们的杂乱无章的 SQL 语句中寻找它下一句需要执行的关键字在哪里. 
效率嘛, 由于我们的感觉神经对秒以下的变化实在不敏感, 暂且就认为自已写的 SQL 顺序无关紧要, "反正没什么变化!", 呵呵.其实服务器对每句 SQL 解析时间都会有详细记录的, 大家可以看一下自已按习惯写的 SQL 和按标准顺序写的SQL解析时间差别有多大. 
因此, 建议大家在平时工作中 SQL 语句按标准顺序写, 一是专业, 二是实用, 呵呵, 不过我觉得最主要的是心里感觉舒服. 
标准的 SQL 的解析顺序为: 
(1).FROM 子句, 组装来自不同数据源的数据 
(2).WHERE 子句, 基于指定的条件对记录进行筛选 
(3).GROUP BY 子句, 将数据划分为多个分组 
(4).使用聚合函数进行计算 
(5).使用 HAVING 子句筛选分组 
(6).计算所有的表达式 
(7).使用 ORDER BY 对结果集进行排序 
举例说明: 在学生成绩表中 (暂记为 tb_Grade), 把 "考生姓名"内容不为空的记录按照 "考生姓名" 分组, 并且筛选分组结果, 选出 "总成绩" 大于 600 分的. 
标准顺序的 SQL 语句为: 
select 考生姓名, max(总成绩) as max总成绩 
from tb_Grade 
where 考生姓名 is not null 
group by 考生姓名 
having max(总成绩) > 600 
order by max总成绩 
在上面的示例中 SQL 语句的执行顺序如下: 
(1). 首先执行 FROM 子句, 从 tb_Grade 表组装数据源的数据 
(2). 执行 WHERE 子句, 筛选 tb_Grade 表中所有数据不为 NULL 的数据 
(3). 执行 GROUP BY 子句, 把 tb_Grade 表按 "学生姓名" 列进行分组 
(4). 计算 max() 聚集函数, 按 "总成绩" 求出总成绩中最大的一些数值 
(5). 执行 HAVING 子句, 筛选课程的总成绩大于 600 分的. 
(7). 执行 ORDER BY 子句, 把最后的结果按 "Max 成绩" 进行排序. 
好了,看了这些之后,我相信大家都知道了SQL中select语句的执行顺序了吧!


第二篇:SQL Select语句完整的执行顺序


SQL Select语句完整的执行顺序SQL Select语句完整的执行顺序:1、from子句组装来自不同数据源的数据;2、where子句基于指定的条件对记录行进行筛选;3、group by子句将数据划分为多个分组;4、使用聚集函数进行计算;5、使用having子句筛选分组;以下结论是通过在Sql Server2000上的实验得出的结论,也可通过查看估计的执行计划(Ctrl+L)来查看执行顺序。1.先执行等号(=)左边是变量的表达式(A类),再执行等号(=)左边是列名的表达式(B类)。例:update tablename set columnName=@variable,@variable=@variable+1 先执行@variable=@variable+1,再执行columnName=@variable2.如果有多个A类(或B类)表达式,按从左到右顺序执行A类(或B类)表达式。例:update tablename set columnName=@variable,@variable=@variable+1,@variable=2*@variable 先执行@variable=@variable+1,再执行@variable=2*@variable,最后执行columnName=@variable3.列名所代表的值永远是原值。例:update tablename set columnName=colunName+1,columnNameBa group by在select 语句中可以使用group by 子句将行划分成较小的组,然后,使用聚组函数返回每一个组的汇总信息,另外,可以使用having子句限制返回的结果集。group by 子句可以将查询结果分组,并返回行的汇总信息Oracle 按照group by 子句中指定的表达式的值分组查询结果。在带有group by 子句的查询语句中,在select 列表中指定的列要么是group by 子句中指定的列,要么包含聚组函数select max(sal),job emp group by job;(注意max(sal),job的job并非一定要出现,但有意义)查询语句的select 和group by ,having 子句是聚组函数唯一出现的地方,在where 子句中不能使用聚组函数。select deptno,sum(sal) from emp where sal>1200 group by deptno having sum(sal)>8500 order by deptno;当在gropu by 子句中使用having 子句时,查询结果中只返回满足having条件的组。在一个sql语句中可以有where子句和having子句。having 与where 子句类似,均用于设置限定条件where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。查询每个部门的每种职位的雇员数select deptno,job,count(*) from emp group by deptno,job;Oracle SQL 性能优化技巧1.选用适合的ORACLE优化器ORACLE的优化器共有3种A、RULE (基于规则) b、COST (基于成本) c、CHOOSE (选择性)设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MO

DE参数的各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS 。你当然也在SQL句级或是会话(session)级对其进行覆盖。为了使用基于成本的优化器(CBO, Cost-Based Optimizer) , 你必须经常运行analyze 命令,以增加数据库中的对象统计信息(object statistics)的准确性。如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运行过analyze命令有关。如果table已经被analyze过, 优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器。在缺省情况下,ORACLE采用CHOOSE优化器,为了避免那些不必要的全表扫描(full table scan) ,你必须尽量避免使用CHOOSE优化器,而直接采用基于规则或者基于成本的优化器。2.访问Table的方式ORACLE 采用两种访问表中记录的方式:A、 全表扫描全表扫描就是顺序地访问表中每条记录。ORACLE采用一次读入多个数据块(database block)的方式优化全表扫描。B、 通过ROWID访问表你可以采用基于ROWID的访问方式情况,提高访问表的效率, ROWID包含了表中记录的物理位置信息。ORACLE采用索引(INDEX)实现了数据和存放数据的物理位置(ROWID)之间的联系。通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高。3.共享SQL语句为了不重复解析相同的SQL语句,在第一次解析之后,ORACLE将SQL语句存放在内存中。这块位于系统全局区域SGA(system global area)的共享池(shared buffer pool)中的内存可以被所有的数据库用户共享。因此,当你执行一个SQL语句(有时被称为一个游标)时,如果它和之前的执行过的语句完全相同, ORACLE就能很快获得已经被解析的语句以及最好的执行路径。ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用。可惜的是ORACLE只对简单的表提供高速缓冲(cache buffering),这个功能并不适用于多表连接查询。数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了。当你向ORACLE提交一个SQL语句,ORACLE会首先在这块内存中查找相同的语句。这里需要注明的是,ORACLE对两者采取的是一种严格匹配,要达成共享,SQL语句必须完全相同(包括空格,换行等)。数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了。共享的语句必须满足三个条件:A、 字符级的比较:当前被执行的语句和共享池中的语句必须完全相同。B、 两个语句所

指的对象必须完全相同:C、两个SQL语句中必须使用相同的名字的绑定变量(bind variables)。4.选择最有效率的表名顺序(只在基于规则的优化器中有效)ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理。在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。当ORACLE处理多个表时,会运用排序及合并的方式连接它们。首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并。如果有3个以上的表连接查询,那就需要选择交叉表(intersection table)作为基础表,交叉表是指那个被其他表所引用的表。5.WHERE子句中的连接顺序ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。6.SELECT子句中避免使用 ' * '当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 '*' 是一个方便的方法。不幸的是,这是一个非常低效的方法。实际上,ORACLE在解析的过程中,会将'*' 依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。7.减少访问数据库的次数当执行每条SQL语句时,ORACLE在内部执行了许多工作:解析SQL语句,估算索引的利用率,绑定变量,读数据块等等。由此可见,减少访问数据库的次数,就能实际上减少ORACLE的工作量。8.使用DECODE函数来减少处理时间使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表。9.整合简单,无关联的数据库访问如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)10.删除重复记录11.用TRUNCATE替代DELETE当删除表中的记录时,在通常情况下,回滚段(rollback segments ) 用来存放可以被恢复的信息。如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况)。而当运用TRUNCATE时,回滚段不再存放任何可被恢复的信息。当命令运行后,数据不能被恢复。因此很少的资源被调用,执行时间也会很短。12.尽量多使用COMMIT只要有可能,在程序中尽量多使用COMMIT,这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少COMMIT所释放的资源:A、 回滚段上用于恢复数据的信息。B、被程序

语句获得的锁。C、 redo log buffer 中的空间。D、ORACLE为管理上述3种资源中的内部花费。13.计算记录条数和一般的观点相反,count(*) 比count(1)稍快,当然如果可以通过索引检索,对索引列的计数仍旧是最快的。例如 COUNT(EMPNO)14.用Where子句替换HAVING子句避免使用HAVING子句,HAVING 只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序,总计等操作。如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销。15.减少对表的查询在含有子查询的SQL语句中,要特别注意减少对表的查询。16.通过内部函数提高SQL效率。17.使用表的别名(Alias)当在SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个Column上。这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。18.用EXISTS替代IN在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下,使用EXISTS(或NOT EXISTS)通常将提高查询的效率。19.用NOT EXISTS替代NOT IN在子查询中,NOT IN子句将执行一个内部的排序和合并。无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历)。为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS。20.用表连接替换EXISTS通常来说 ,采用表连接的方式比EXISTS更有效率21.用EXISTS替换DISTINCT当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT。一般可以考虑用EXIST替换

更多相关推荐:
使用plsql执行计划进行sql调优

使用plsql执行计划进行sql调优转载一段SQL代码写好以后可以通过查看SQL的执行计划初步预测该SQL在运行时的性能好坏尤其是在发现某个SQL语句的效率较差时我们可以通过查看执行计划分析出该SQL代码的问题...

oracle定时执行plsql

DBMSJob包的用法包含以下子过程Broken过程change过程Interval过程Isubmit过程NextDate过程Remove过程Run过程Submit过程UserExport过程What过程1Br...

PLSQL 执行sql语句 F5 快捷键的解释

通过F5查看到的执行计划其实是plsqldeveloper工具内部执行查询plantable表然后格式化的结果selectfromplantablewherestatementid3939其中Descripti...

Oracle查看执行计划

有三种方法1Explainplanexplainplanforselectfromaa查看结果selectfromtabledbmsxplandisplay2AutotraceSettimingon记录所用时间...

Oracle数据库执行计划的一些基本概念

Oracle数据库执行计划的一些基本概念一相关的概念Rowid的概念rowid是一个伪列既然是伪列那么这个列就不是用户定义而是系统自己给加上的对每个表都有一个rowid的伪列但是表中并不物理存储ROWID列的值...

Oracle执行计划详解

Oracle执行计划详解目录一相关的概念Rowid的概念RecursiveSql概念Predicate谓词DRivingTable驱动表ProbedTable被探查表组合索引concatenatedindex可...

Oracle执行计划 SQL语句执行效率问题查找与解决方法

Oracle的SQL语句执行效率问题查找与解决方法一识别占用资源较多的语句的方法4种方法1测试组和最终用户反馈的与反应缓慢有关的问题2利用VSQLAREA视图提供了执行的细节执行读取磁盘和读取缓冲区的次数数据列...

oracle执行计划

0SELECTSTATEMENT864200000011TABLEACCESSFULLDAVE86420000001统计信息0recursivecalls0dbblockgets4consistentgets0...

Oracle SQL执行计划的简单分析

我们对SQL语句进行调优时非常重要的一个方法就是分析SQL的执行计划查看Oracle中SQL语句的执行计划有很多方法例如通过PLSQLDeveloperEM或者SQLPLUS工具等这里以SQLPLUS为例在SQ...

开启sql语句执行计划

二通过sqlplus1最简单的办法SqlgtsetautotraceonSqlgtselectfromdual执行完语句后会显示explainplan与统计信息这个语句的优点就是它的缺点这样在用该方法查看执行时...

sql生成执行计划时出错

普通用户scott开启追踪日志时报错SCOTTsungtsetautotracetraceonlySP20618CannotfindtheSessionIdentifierCheckPLUSTRACErolei...

看懂SqlServer查询计划

对于SqlServer的优化来说可能优化查询是很常见的事情关于数据库的优化本身也是一个涉及面比较的广的话题本文只谈优化查询时如何看懂SqlServer查询计划由于本人对SqlServer的认识有限如有错误也恳请...

使用plsql执行计划进行sql调优(1篇)