Oracle 执行顺序 及 驱动表和被驱动表


oracle驱动表以及如何确定驱动表

驱动表普遍认为是由SQL语句的写法决定的,简单的说,就是FROM语句后面的表列表中的最后一个。由于SQL语句是从后向前进行分析,Oracle会根据FROM语句从后到前将各个表依次连接起来。

首先理解执行顺序

先从最开头一直往右看,直到看到最右边的并列的地方,对于不并列的,靠右的先执行:对于并列的,靠上的先执行。
 即并列的缩进,从上往下执行,非并列的缩进块,从下往上执行。

1.    如果所连接的表A和B,A表长度远远大于B表,建议从较大的A表上驱动。(简言之 大值为驱动表)

2.  如果Where子句中含有选择性条件,Where No=20,将最具有选择性部分放在表达式最后。

3.  如果只有一个表有索引,另一表无索引,无索引的表通常作为驱动表。

A表的No列以被索引,而B表的No列没被索引,

则应当B表作为驱动表,A表作为被驱动表。 

RBO或者CBO没有分析table的情况下,对于2个表的操作,FROM子句中,RBO选择最右的表作为驱动表(一般也就是from 中最后的表作为驱动表 )。

所以 对于NESTED LOOPS、HASH JOIN、SORT MERGE JOIN方式,驱动表选择较小的表 (放在from 最右端),速度会更快;

存在主、外键关系的表,由于主键由oracle自动建立索引,外键上最好也建索引,以避免全表扫描 。

而对于3个或以上table连接查询,对于FROM子句,RBO以从右到左的顺序处理表连接,也就是from 子句最右端table作为驱动表。

SQL>CREATE TABLE T1 AS SELECT * FROM USER_TABLES;

表已创建。

SQL>CREATE TABLE T2 AS SELECT * FROM USER_INDEXES;

表已创建。

SQL>SET AUTOT ON EXP
SQL> SELECT COUNT(*) FROM T1, T2 WHERE T1.TABLE_NAME = T2.TABLE_NAME;

COUNT(*)
----------
37

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 MERGE JOIN
3 2 SORT (JOIN)
4 3 TABLE ACCESS (FULL) OF ‘T2‘
5 2 SORT (JOIN)
6 5 TABLE ACCESS (FULL) OF ‘T1‘

T2 是驱动表

SQL>
SELECT COUNT(*) FROM T2, T1 WHERE T1.TABLE_NAME = T2.TABLE_NAME;

COUNT(*)
----------
37

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 MERGE JOIN
3 2 SORT (JOIN)
4 3 TABLE ACCESS (FULL) OF ‘T1‘
5 2 SORT (JOIN)
6 5 TABLE ACCESS (FULL) OF ‘T2‘

根据这个例子,可以看出,SQL语句的写法对于驱动表的影响。

然而,实际上驱动表和连接顺序的选择要比上面的观点复杂的多,下面对稍微调整一下这个例子。
T1 是驱动表

SQL> ALTER TABLE T1 ADD CONSTRAINT PK_T1 PRIMARY KEY
(TABLE_NAME);

表已更改。

SQL>
SELECT COUNT(*) FROM T1, T2 WHERE T1.TABLE_NAME = T2.TABLE_NAME;

COUNT(*)

----------

37

Execution
Plan

----------------------------------------------------------

0 SELECT STATEMENT ptimizer=CHOOSE

1 0 SORT (AGGREGATE)

2 1 NESTED LOOPS

3 2 TABLE ACCESS (FULL) OF ‘T2‘

4 2 INDEX (UNIQUE SCAN) OF ‘PK_T1‘ (UNIQUE)

SQL>
SELECT COUNT(*) FROM T2, T1 WHERE T1.TABLE_NAME = T2.TABLE_NAME;

COUNT(*)

----------

37

Execution
Plan

----------------------------------------------------------

0 SELECT STATEMENT ptimizer=CHOOSE

1 0 SORT (AGGREGATE)

2 1 NESTED LOOPS

3 2 TABLE ACCESS (FULL) OF ‘T2‘

4 2 INDEX (UNIQUE SCAN) OF ‘PK_T1‘ (UNIQUE)


仅仅是给T1增加了一个主键,就发现不管SQL语句怎么写驱动表都是T2

即使是RBO,确定表连接顺序的规则也是比较复杂的:

1.优化器产生一系列连接顺序,每次均把不同的表作为驱动表。而且,优化器根据下面的算法产生每个连接顺序。

为了确定连接顺序中各个表的位置,优化器根据RBO执行计划的排名,在剩余的表中找到表访问路径排名最高的表,然后不断的重复这个过程,依次确定连接顺序中每个表的前后顺序。

对于连接顺序中的每张表,优化器根据执行计划的排名选择一种连接方式将当前表和前面的表或数据源连接在一起。

2.优化器在执行计划的结果集中进行选择。

优化器的目标是最大程度的选择内部表采用索引扫描方式的 NESTED LOOPS 连接操作。

通常情况下,优化器在选择执行计划时,不会考虑表在FROM语句中出现的顺序。

优化器依次根据下面的规则来作出选择:

优化器选择执行计划使得内部表为全表扫描的NESTED LOOPS连接尽可能的少;

如果采用上面的条件出现了平局的情况,则优化器选择尽可能少出现SORT MERGE操作的执行计划;

如果仍然出现平局的情况,则优化器将选择表访问路径中排名最高的表作为驱动表;

如果这时仍然是平局,则优化器会把 FROM 语句中最后出现的表最为驱动表

来自为知笔记(Wiz)

时间: 2024-10-11 06:57:04

Oracle 执行顺序 及 驱动表和被驱动表的相关文章

Mysql 语句执行顺序

转载自:http://blog.csdn.net/jintao_ma/article/details/51253356 1.这样一个问题,作为一个开发人员需要掌握数据库的哪些东西?  在开发中涉及到数据库,基本上只用到了sql语句,如何写sql以及对其进行优化就比较重要,那些mysql的厚本书籍针对的是DBA,我们只需要学习其中的sql就可以了. 2.既然会写sql是目标,那么怎么才能写好sql.学习下面几点: 1)Mysql的执行顺序,这个是写sql的核心,之前遇到的一些错误就是因为对其不了解

数据库之表查询,单表、多表,子查询

基本查询语句及方法 from where group by having distinct order by limit .... 连表 inner join left join right join union 子查询 书写顺序 select id,name from emp where id > 3 and id < 6;执行顺序 from # 确定到底是哪站表 where # 根据过来条件 筛选数据 select # 拿出筛选出来的数据中的某些字段 select * from emp\G

Oracle中查询关键字select--from--where--group by--having--order by执行顺序

select--from--where--group by--having--order by 这6个查询关键字的执行顺序: 1.from组装来自不同数据源的数据:2.where基于指定的条件对记录行进行筛选:3.group by子句将数据划分为多个分组:4.使用聚集函数进行计算:5.使用having子句筛选分组:6.计算所有的表达式:7.select 集合输出:8.使用order by对结果集进行排序. 以下例子基于Oracle自带表空间hr 例子1:having和select的执行说明 情景

SQL Server中多表连接时驱动顺序对性能的影响

原文:SQL Server中多表连接时驱动顺序对性能的影响 本文出处:http://www.cnblogs.com/wy123/p/7106861.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他) 最近在SQL Server中多次遇到开发人员提交过来的有性能问题的SQL,其表面的原因是表之间去的驱动顺序造成的性能问题,具体表现在(已排除其他因素影响的情况下),存储过程偶发性的执行时间超出预期,甚至在调试的时候

Oracle一个事务中的Insert和Update执行顺序

今天碰到了一个奇怪的问题,是关于Oracle一个事务中的Insert和Update语句的执行顺序的问题. 首先详细说明下整个过程: 有三张表:A,B,C,Java代码中有一段代码是先在表A中插入一条数据,然后再更新表B的两个字段,更新的两个字段是特定值.并且插入和更新在一个事务中. 有个需求需要在表A添加一个Insert的行级触发器,在触发器里,插入表A一行记录后去表B查看更新的两个字段是否满足特定条件, 如果表B的两个字段同时等于特定值,则把表A和表B的数据整合下放到表C.触发器的初衷就是这样

Oracle中的一些查询语句及其执行顺序

查询条件: 1)LIKE:模糊查询,需要借助两个通配符,%:表示0到多个字符:_:标识单个字符. 2)IN(list):用来取出符合列表范围中的数据. 3)NOT IN(list): 取出不符合此列表中的数据记录. 4)BETWEEN-AND-:用来查询符合某个值域范围条件的数据,最常见的是使用在数字类型的数据范围上,但对字符类型和日期类型数据也同样适用.for example:    SELECT ename, sal FROM emp WHERE sal BETWEEN 1500 AND 3

闲谈Oracle执行计划的步骤顺序

经过长时间学习Oracle,于是和大家分享一下,看完本文你肯定有不少收获,希望本文能教会你更多东西.Oracle执行计划的每一步返回一组行,它们或者为下一步所使用,或者在最后一步时返回给发出SQL语句的用户或应用.由每一步返回的一组行叫做行源(row source).下面得树状图显示了从一步到另一步行数据的流动情况.每步的编号反映了在你观察Oracle执行计划时所示步骤的顺序(如何观察Oracle执行计划将被简短地说明).一般来说这并不是每一步被执行的先后顺序. Oracle执行计划的每一步或者

oracle 各部分执行顺序

查询语句的执行顺序: 1.FROM 子句:执行顺序为从后往前.从右到左.数据量较少的表尽量放在后面. 2.WHERE子句:执行顺序为自下而上.从右到左.将能过滤掉最大数量记录的条件写在WHERE 子句的最右. 3.GROUP BY:执行顺序从左往右分组,最好在GROUP BY前使用WHERE将不需要的记录在GROUP BY之前过滤掉. 4.HAVING 子句:消耗资源.尽量避免使用,HAVING 会在检索出所有记录之后才对结果集进行过滤,需要排序等操作. 5.SELECT子句:少用*号,尽量取字

公用表(CTE)表达式引发的改变执行顺序同WHERE条件顺序引发的bug

以下模拟一下CTE出错 /*测试环境 Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64) Apr 2 2010 15:48:46 Copyright (c) Microsoft Corporation Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) */ 生成表Tab数据: --> --> (Roy)生成測試數據