`
jackroomage
  • 浏览: 1217811 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

ORACLE表连接方式分析及常见用法

阅读更多
                                      ORACLE表连接方式分析及常见用法


摘要: 针对在数据仓库环境下,由于超大数据量的处理而产生的效率问题,本文深入分析了ORACLE表的几种连接方式、特点、

适用范围,以及对于如何使用和优化做了详细的探讨。

关键字: 数据仓库 ORACLE 表连接

一 引言

数据仓库技术是目前已知的比较成熟和被广泛采用的解决方案,用于整和电信运营企业内部所有分散的原始业务数据,并通

过便捷有效的数据访问手段,可以支持企业内部不同部门,不同需求,不同层次的用户随时获得自己所需的信息。数据仓库

系统需要能够及时地追踪和分析大量的历史数据,并能够及时做出分析和预测,因此实时性是一个非常重要的指标。ORACLE

由于可靠性、高性能等方面的特点,在电信行业大部分的数据仓库系统中担当了后台数据库的角色。由于电信行业的特点,

处理的数据量十分庞大,处理的时间长。尤其是对于大表之间的关联操作,有的大表的记录数达到数亿条,处理时间更是漫

长,这成为影响数据库运行效率的主要因素。因此,对于数据库的性能优化相当重要。性能优化是个很大的课题,需要综合

考虑,从服务器、磁盘、网络、ORACLE实例、ORACLE SQL等多方面着手。本文着重分析ORACLE SQL优化中对于系统性能影响

极大的表连接方式、特点、适用范围,并对如何使用和优化做了详细的探讨。


二 表的连接

表的连接是指在一个SQL语句中通过表与表之间的关联,从一个或多个表检索出相关的数据。连接是通过SQL语句中FROM从句

的多个表名,以及WHERE从句里定义的表之间的连接条件来实现的。如果一个SQL语句的关联表超过两个,那么连接的顺序如

何呢?ORACLE首先连接其中的两个表,产生一个结果集;然后将产生的结果集与下一个表再进行关联;继续这个过程,直到

所有的表都连接完成;最后产生所需的数据。下面都以两个表的连接为例

create table user_info(user_name char(10),user_id char(10));

create table dev_info(dev_no char(10),user_id char(10),dev_type char(10));

说明和分析表的各种连接方式。

ORACLE 从6的版本开始,优化器使用4种不同的表的连接方式:

Ø 嵌套循环连接(NESTED LOOP JOIN)

Ø 群集连接 (CLUSTER JOIN)

Ø 排序合并连接(SORT MERGE JOIN)

Ø 笛卡尔连接 (CARTESIAN JOIN)

ORACLE 7.3中,新增加了

Ø 哈希连接(HASH JOIN)。

在ORACLE 8中,新增加了

Ø 索引连接(INDEX JOIN)。

这六种连接方式都有其独特的技术特点,在一定的条件下,可以充分发挥高效的性能。

但是也都有其局限性,如果使用不当,不仅不能提高效率,反而会严重影响系统的性能。因此,深入地探讨连接方式的内部

运行机制对于性能优化是必要的。


1 嵌套循环连接

嵌套循环连接的内部处理的流程:

1) Oracle 优化器根据基于规则RBO或基于成本CBO的原则,选择两个表中的一个作为驱动表,并指定其为外部表。

2) Oracle 优化器再将另外一个表指定为内部表。

3) Oracle从外部表中读取第一行,然后和内部表中的数据逐一进行对比,所有匹配的记录放在结果集中。

4) Oracle读取外部表中的第二行,再和内部表中的数据逐一进行对比,所有匹配的记录添加到结果集中。

5) 重复上述步骤,直到外部表中的所有纪录全部处理完。

6) 最后产生满足要求的结果集。

通过查询SQL语句的执行计划可以看出哪个表是外部表,哪个为内部表。

如 select a.user_name,b.dev_no

from user_info a, dev_info b

where a.user_id = b.user_id;

上面的表是外部表,即驱动表


下面的表是内部表

的执行计划:

SELECT STATEMENT Optimizer=CHOOSE

NESTED LOOPS

TABLE ACCESS (FULL) OF 'USER_INFO'

TABLE ACCESS (FULL) OF 'DEV_INFO'

使用嵌套循环连接是一种从结果集中提取第一批记录最快速的方法。在驱动行源表(就是正在查找的记录)较小、或者内部行

源表已连接的列有惟一的索引或高度可选的非惟一索引时, 嵌套循环连接效果是比较理想的。嵌套循环连接比其他连接方法

有优势,它可以快速地从结果集中提取第一批记录,而不用等待整个结果集完全确定下来。这样,在理想情况下,终端用户就可

以通过查询屏幕查看第一批记录,而在同时读取其他记录。不管如何定义连接的条件或者模式,任何两行记录源可以使用嵌套

循环连接,所以嵌套循环连接是非常灵活的。

然而,如果内部行源表(读取的第二张表)已连接的列上不包含索引,或者索引不是高度可选时, 嵌套循环连接效率是很低的。

如果驱动表的记录非常庞大时,其他的连接方法可能更加有效。

可以通过在SQL语句中添加HINTS,强制ORACLE优化器产生嵌套循环连接的执行计划。

select /*+ use_nl(a b) */ a.user_name,b.dev_no

from user_info a, dev_info b

where a.user_id = b.user_id;


2 群集连接(CLUSTER JOIN)

群集连接实际上是嵌套循环连接的一种特例。如果所连接的两张源表是群集中的表,即两张表属于同一个段(SEGMENT),,

那么ORACLE能够使用群集连接。处理的过程是:ORACLE从第一张行源表中读取第一行,然后在第二张行源表中使用CLUSTER索

引查找能够匹配到的纪录;继续上面的步骤处理行源表中的第二行,直到所有的记录全部处理完。

群集连接的效率极高,因为两个参加连接的行源表实际上处于同一个物理块上。但是,群集连接也有其限制,没有群集的两

个表不可能用群集连接。所以,群集连接实际上很少使用。


3 排序合并连接(SORT MERGE JOIN)

排序合并连接内部处理的流程:

1) 优化器判断第一个源表是否已经排序,如果已经排序,则到第3步,否则

到第2步。

2) 第一个源表排序

3) 优化器判断第二个源表是否已经排序,如果已经排序,则到第5步,否则

到第4步。

4) 第二个源表排序

5) 已经排过序的两个源表进行合并操作,并生成最终的结果集。

在缺乏数据的选择性或者可用的索引时,或者两个源表都过于庞大(所选的数据超过表记录数的5%)时,排序合并连接将比嵌套

循环连更加高效。

排列合并连接需要比较大的临时内存块,以用于排序,这将导致在临时表空间占用更多的内存和磁盘I/O。

select a.user_name,b.dev_no

from user_info a, dev_info b

where a.user_id > b.user_id;

Plan

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

SELECT STATEMENT Optimizer=CHOOSE (Cost=7 Card=336 Bytes=16128)

MERGE JOIN (Cost=7 Card=336 Bytes=16128)

SORT (JOIN) (Cost=4 Card=82 Bytes=1968)

TABLE ACCESS (FULL) OF 'USER_INFO' (Cost=2 Card=82 Bytes=1968)

SORT (JOIN) (Cost=4 Card=82 Bytes=1968)

TABLE ACCESS (FULL) OF 'DEV_INFO' (Cost=2 Card=82 Bytes=1968)

可以通过在SQL语句中添加HINTS,强制ORACLE优化器产生排序合并连接的执行计划。

select /*+ use_merge(a b) */ a.user_name,b.dev_no

from user_info a, dev_info b

where a.user_id > b.user_id;

排序合并连接是基于RBO的。


4 笛卡尔连接 (CARTESIAN JOIN)

笛卡尔连接是指在sql语句中没有写出表连接的条件,优化器把第一个表的每一条记录和第二个表的所有纪录相连接。如果第

一个表的纪录数为m, 第二个表的纪录数为m,则会产生m*n条纪录数。

下面的查询,未指名连接条件,就会产生笛卡尔连接。

select a.user_name,b.dev_no

from user_info a ,dev_info b;

由于笛卡尔连接会导致性能很差的SQL,因此一般也很少用到。

5哈希连接

当内存能够提供足够的空间时,哈希(HASH)连接是Oracle优化器通常的选择。哈希连接中,优化器根据统计信息,首先选择两

个表中的小表,在内存中建立这张表的基于连接键的哈希表;优化器再扫描表连接中的大表,将大表中的数据与哈希表进行

比较,如果有相关联的数据,则将数据添加到结果集中。

当表连接中的小表能够完全cache到可用内存的时候,哈希连接的效果最佳。哈希连接的成本只是两个表从硬盘读入到内存的

成本。

但是,如果哈希表过大而不能全部cache到可用内存时,优化器将会把哈希表分成多个分区,再将分区逐一cache到内存中。

当表的分区超过了可用内存时,分区的部分数据就会临时地写到磁盘上的临时表空间上。因此,分区的数据写磁盘时,比较

大的区间(EXTENT)会提高I/O性能。ORACLE推荐的临时表空间的区间是1MB。临时表空间的区间大小由UNIFORM SIZE指定。

当哈希表构建完成后,进行下面的处理:

1) 第二个大表进行扫描

2) 如果大表不能完全cache到可用内存的时候,大表同样会分成很多分区

3) 大表的第一个分区cache到内存

4) 对大表第一个分区的数据进行扫描,并与哈希表进行比较,如果有匹配的纪录,添加到结果集里面

5) 与第一个分区一样,其它的分区也类似处理。

6) 所有的分区处理完后,ORACLE对产生的结果集进行归并,汇总,产生最终的结果。

当哈希表过大或可用内存有限,哈希表不能完全CACHE到内存。随着满足连接条件的结果集的增加,可用内存会随之下降,这

时已经CACHE到内存的数据可能会重新写回到硬盘去。如果出现这种情况,系统的性能就会下降。

当连接的两个表是用等值连接并且表的数据量比较大时,优化器才可能采用哈希连接。哈希连接是基于CBO的。只有在数据库

初始化参数HASH_JOIN_ENABLED设为True,并且为参数PGA_AGGREGATE_TARGET设置了一个足够大的值的时候,Oracle才会使用哈

希边连接。HASH_AREA_SIZE是向下兼容的参数,但在Oracle9i之前的版本中应当使用HASH_AREA_SIZE。当使用ORDERED提示

时,FROM子句中的第一张表将用于建立哈希表。

select a.user_name,b.dev_no

from user_info a, dev_info b

where a.user_id = b.user_id;

Plan

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

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=5 Card=82 Bytes=3936

)

1 0 HASH JOIN (Cost=5 Card=82 Bytes=3936)

2 1 TABLE ACCESS (FULL) OF 'USER_INFO' (Cost=2 Card=82 Bytes

=1968)

3 1 TABLE ACCESS (FULL) OF 'DEV_INFO' (Cost=2 Card=82 Bytes=

1968)

可以通过在SQL语句中添加HINTS,强制ORACLE优化器产生哈希连接的执行计划。

select /*+ use_hash(a b)*/ a.user_name,b.dev_no

from user_info a, dev_info b

where a.user_id = b.user_id;

当缺少有用的索引时,哈希连接比嵌套循环连接更加有效。哈希连接也可能比嵌套循环连接更快,因为处理内存中的哈希表

比检索B_树索引更加迅速。

6 索引连接

如果一组已存在的索引包含了查询所需要的所有信息,那么优化器将在索引中有选择地生成一组哈希表。可通过范围或者快

速全局扫描访问到每一个索引,而选择何种扫描方式取决于WHERE子句中的可有条件。在一张表有大量的列,而您只想访问有

限的列时,这种方法非常有效。WHERE子句约束条件越多,执行速度越快。因为优化器在评估执行查询的优化路径时,将把约

束条件作为选项看待。您必须在合适的列(那些满足整个查询的列)上建立索引,这样可以确保优化器将索引连接作为可选

项之一。这个任务通常牵涉到在没有索引,或者以前没有建立联合索引的列上增加索引。相对于快速全局扫描,连接索引的

优势在于:快速全局扫描只有一个单一索引满足整个查询;索引连接可以有多个索引满足整个查询。

假设表dev_info上有两个索(一个在dev_no,一个在dev_type 上)。

作如下的查询

select dev_no,dev_type

from user_info

where user_id = ‘U101010’

and dev_type = ‘1010’;


三 几种主要表连接的比较

类别
嵌套循环连接
排序合并连接
哈希连接

优化器提示
USE_NL
USE_MERGE
USE_HASH

使用的条件
任何连接
主要用于不等价连接,如<、 <=、 >、 >=;

但是不包括 <>
仅用于等价连接

相关资源
CPU、磁盘I/O
内存、临时空间
内存、临时空间

特点
当有高选择性索引或进行限制性搜索时效率比较高,能够快速返回第一次的搜索结果。
当缺乏索引或者索引条件模糊时,排序合并连接比嵌套循环有效。
当缺乏索引或者索引条件模糊时,哈希连接连接比嵌套循环有效。通常比排序合并连接快。

在数据仓库环境下,如果表的纪录数多,效率高。


缺点
当索引丢失或者查询条件限制不够时,效率很低;

当表的纪录数多时,效率低。
所有的表都需要排序。它为最优化的吞吐量而设计,并且在结果没有全部找到前不返回数据。
为建立哈希表,需要大量内存。第一次的结果返回较慢。




四 结束语

深入地理解和掌握oracle的表连接对于优化数据库的性能至关重要。由于优化器选择方式的不同,以及统计信息的缺失或统

计信息的不准确,ORACLE自动选择的表连接方式不一定是最优的。当SQL语句的执行效率很低时,可通过auto trace对执行计

划进行跟踪和分析。当出现多表连接时,需要仔细分析是否有更佳的连接条件。根据系统的特点,必要时可以在SQL中添加

HINTS,从而改变SQL的执行计划,从而达到性能优化的目的。



分享到:
评论

相关推荐

    Oracle数据库表连接方式及常见用法

    Oracle 数据库表连接方式及常见用法 Oracle 数据库表连接方式是指在数据库中连接两个或多个表以获取所需的数据。这些连接方式包括相等连接、外连接、不等连接、自连接和哈希连接等。本文将详细介绍这些连接方式的...

    Oracle常见用法

    以下是对Oracle中一些常见用法的详细说明: **SQL查询语句**: SQL(Structured Query Language)是用于管理和处理关系数据库的标准语言。在Oracle中,`SELECT`语句是最基本的查询命令,用于从数据库中检索数据。 ...

    php连接oracle数据库的方法(测试成功)

    2. 然后安装Oracle Instant Client,这是一个轻量级的Oracle客户端,提供了连接Oracle数据库所需的基本组件。 3. 在php.ini文件中启用oci8扩展,这一步需要在php.ini文件中设置extension=php_oci8以启用OCI8扩展。 4...

    Oracle连接查找

    根据给定的文件信息,“Oracle连接查找”这一主题涵盖了内连接(Inner Join)、外连接(Outer Join)以及相关的实例和对比。接下来,我们将深入探讨这些知识点。 ### 一、内连接(Inner Join) 内连接是连接类型中...

    从vc连接到oracle数据库从vc连接到oracle数据库

    在VC++环境中与Oracle数据库进行连接是开发过程中常见的任务,主要涉及到ODBC(Open Database Connectivity)和Oracle的OCI(Oracle Call Interface)等技术。本文将详细介绍如何在VC++中建立Oracle数据库连接,以及...

    oracle HINTS用法

    以上就是Oracle Hints的一些常见用法。合理使用这些Hints可以帮助优化查询性能,提高系统的整体响应速度。然而,在使用时需要注意,过度依赖Hints可能会导致维护问题,因为随着数据结构的变化,硬编码的查询计划可能...

    oracle高级用法

    常见的分区方式有范围分区、列表分区、哈希分区和复合分区。 七、物化视图 物化视图是预先计算好的查询结果,可以显著提高查询性能。特别是对于经常执行的复杂聚合查询,物化视图能极大地减少计算时间。 八、...

    Oracle 左连接(+)加号用法及常用语法之间的关系

    本文将深入探讨Oracle左连接(+)加号的用法以及与其它常见语法的关系。 首先,我们创建两个测试表`test_left_a`和`test_left_b`,并填充一些测试数据,如下所示: ```sql CREATE TABLE test_left_a (a VARCHAR2(50)...

    oracle手册,详解SQL用法

    Oracle数据库是世界上最广泛使用的数据库系统之一,其强大的SQL支持使得数据管理、查询和分析变得高效。本手册将深入探讨Oracle SQL的用法,包括各种函数的使用、数据类型的转换以及查询语句的语法。 首先,Oracle...

    SQL优化过程中常见Oracle中&quot;HINT&quot;的30个用法

    以上列出了30个常见的Oracle`HINT`及其基本用法。在实际应用中,可以根据具体的查询需求和性能目标灵活运用这些`HINT`来优化SQL查询,从而显著提高系统的响应速度和整体性能。需要注意的是,在使用`HINT`时应谨慎...

    Oracle开发的一些简单的用法

    本文将深入解析“Oracle开发的一些简单的用法”,从基本操作到高级功能,为读者提供一份详实的指南。 ### Oracle基础操作 #### 1. 启动与停止Oracle服务 - **启动Oracle服务**:通过执行`...

    oracledb.zip

    封装的`oracledb`模块简化了原生模块的调用方式,提高了开发效率。在`oracledb.zip`中,主要的封装可能包括以下几点: 1. **连接管理**:封装模块可能提供了更友好的连接池管理,比如自动创建和回收连接,减少手动...

    Oracle数据库学习指南

    19.Delphi 3_0中连接数据库的三种方式 20.远程数据库的访问 21.监控数据库性能的SQL 22.简单实现数据库表空间的备份或迁移 23.简析REDO LOGFILE 24.理解和使用Oracle 8i分析工具-LogMiner 25.哪些初始...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    其三、职业方向多:Oracle数据库管理方向、Oracle开发及系统架构方向、Oracle数据建模数据仓库等方向。 四、 如何学习 认真听课、多思考问题、多动手操作、有问题一定要问、多参与讨论、多帮组同学 五、 体系结构 ...

    java操作pageoffice自带印章连接oracle数据库

    总的来说,Java操作PageOffice自带印章连接Oracle数据库是企业级应用中的常见需求,通过合理地使用PageOffice提供的API和Java的数据库连接功能,可以有效地完成这一任务。在开发过程中,注意代码的可读性和维护性,...

    Oracle中的日期类型的用法

    ### Oracle中的日期类型详解 ...以上内容详细介绍了Oracle数据库中日期类型的基本用法、数据存储方式、显示格式以及插入和查询时的注意事项,旨在帮助初学者快速掌握Oracle日期处理的关键概念,避免常见的错误和陷阱。

    ORACLE常见问题.rar

    这份“ORACLE常见问题.rar”压缩包包含了一份PDF文档,针对初学者和中级学习者提供了Oracle相关的学习资料,旨在帮助他们解决在学习和使用过程中可能遇到的问题。 1. **Oracle数据库基础** - 数据库概念:理解什么...

Global site tag (gtag.js) - Google Analytics