您的位置:首页 > 数据库 > Oracle

oracle表联接(三)

2016-03-10 01:06 274 查看
oracle表联接类型:嵌套循环联结、散列联结、排序-合并联结、笛卡尔积联结、外联结。

在确定sql语句的执行计划的时候,优化器必须做出几个关键的选择:

首先,要确定查询中所用到的每个表最合适的访问方法。基本就2个选择:索引扫描或全表扫描。

其次,一旦选定了访问方法,就必须选定联结方法。表将会被逐对进行联结,前一次的联结结果的数据行源被用来与下一个表进行联结,直到所有表都被联结并获得最终的结果集。

注意:每个联结方法都有2个表。所访问的第一张表通常被称为驱动表,访问的第二张表则被称为内层表或被驱动表。如何选择呢??优化器使用统计信息和where子句中的筛选条件计算每个表分别返回多少行数据来确定那张表是驱动表。预估大小最小(就块,数据行、字节而言)的表通常被作为驱动表。尤其是当优化器可以确定其中的一张表基于unique或primary key约束将最多返回一行的时候,这样的表在联结过程中将放在前面。

下图,4个表的联结过程:



1、嵌套循环联结

嵌套循环联结:使用一次访问运算所得到的结果集中的每一行来与另一个表进行对碰。简单说就是一个循环嵌套在另一个循环当中。外层循环就是一个只使用where子句中的属于驱动表的条件对它查询;经过外层条件筛选并被确认匹配条件后,这些行就会逐个进入内层循环中。然后再基于联结列进行逐行检查是否与被联结表中的某一行匹配。如果这一行与内层表中某一行匹配,就将会被传递到查询计划的下一个步或者如果没有更多步骤的话直接被包含在最终的结果集中。

什么情况下效率高:如果结果集的大小是有限的(较小时)并且在用来联结的列上有索引的话,这时联结的效率通常是最高的。

运算成本:主要是读取外层表中的每一行并将其与所匹配的内层表中的行联结所需的成本,最终结果集需要访问的块数。

好处:所使用的内存是非常少的。因为数据行集一次只加工一行,所需开支也是非常小的。除了要建立一个很大的数据集需要较长时间,它也适合进行大数据集加工的。

执行计划:select empno, ename, dname, loc from emp, dept where emp.deptno = dept.no;



4 - access(emp.deptno = dept.deptno)

注意:nested loops运算后所列出的第一个是驱动表,将会采用为它选定的方法来访问。

为什么使用emp表作为驱动表??

答:emp表的deptno列没有索引,访问这个表的唯一方法是全表扫描。由于嵌套循环联结方式就是对外层表的每一行进行内联结,如果将dept表选为驱动表,对于dept表中的每一行都要全表扫描emp表,效率低。相反使用emp作为驱动表,使用dept表的deptno列索引,内层循环可以从dept表中直接访问数据行。

2、排序-合并联结

排序-合并联结:独立的读取需要联结的两张表,对每张表中的数据行(仅仅是那些满足where子句条件的数据行)按照联结键排序,然后对排序后的数据行集进行合并。

缺点:这种联结方法排序的开销是非常大的,但合并的过程是非常快的。

特点:这种联结方法将会访问所需的数据块后,在内存中(如果没有足够的内存的话,将使用临时磁盘空间)进行排序合并。

一般最适合数据筛选条件有限并返回有限数据行的查询。总的来说,条件为非等式的时候排序-合并联结通常是最好的选择。

执行计划:select /*+ ordered*/ empno, ename, dname, loc from emp, dept where emp.deptno = dept.no;



3、散列联结

散列联结:1、首先用where子句中的筛选标准来独立的读取要进行联结的2个表。

2、基于表和索引的统计信息,被确定为返回最少行数的表被完全散列化到内存中(这个散列表包含了原表所有数据行并被基于将联结键转化为散列值的随机函数 载入到散列桶中)。

3、读取另一张较大的表并对联结键列应用散列函数。然后利用得到的散列值对较小的在内存中的散列表进行探测匹配。较大的表只读取一次,并检查其中的每一行来与内存中较小的散列表匹配。

注意:与嵌套循环联结执行计划不同,较小的散列表放在前面而较大的探测表放在后面(这个例子中,实际较大的表示驱动表)。

决定那个表最小的不仅取决于数据行还取决于这些行的大小,因为整个行都必须要存放在散列表中。

特点:散列联结只有在相等的情况下才能进行。当数据行源较大并且结果集也较大的情况下更倾向于考虑散列联结。

执行计划:select empno, ename, dname, loc from emp, dept where emp.deptno = dept.no;



1 access(emp.deptno = dept.deptno)

ora_hash函数生成散列值。该函数有3个参数:一个任何基本类型的输入,最大散列桶值(最小值0),一个种子值(默认是0)。

4、笛卡尔联结

笛卡尔联结:发生在当一张表中的所有行与另一张表中所有行联结的时候。结果集总行数等于A表的行数乘以B表行数。

缺点:可能导致很多重复的结果集。

什么情况下产生笛卡尔联结:通常当联结条件被忽略或忽视以致没有指定的联结列时。

执行计划:select empno, ename, dname, loc from emp, dept



buffer sort的出现,并不是一次真正的排序。而是2个表每一行都要进行联结,使用缓冲区排序机理来将第二张表数据块从缓冲区缓存中复制出并放入到私有内存中,避免缓冲缓存中的同一数据块被一次又一次访问。

5、外联结

外联结返回一张表的所有行以及另一张联结表中满足联结条件的行数据。oracle使用+字符(oracle特有语法)来表明进行外联结。+号放在一对圆括号中,位于只有匹配才会返回数据行的表联结条件旁。

外联结可以与任何联结方法一起使用,并通过在常规运算名称后面加上outer命令来表示。例如:nested loops outer

oracle外面联结语法不支持全外联结。全外联结将会从左到右以及从右到左对两个表进行联结。返回2个表中所有匹配的数据行以及每个表中所独有的行。

全外联结的执行计划:select e1.ename, e1.deptno, e1.job, e2.ename, e2.deptno, e2.job from e1 full outer join e2 on(e1.empno = e2.empno)



全外联结执行了2个独立的查询块,然后通过union-all将2个结果相加。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: