- 浏览: 1098690 次
- 性别:
- 来自: 南京
博客专栏
-
Oracle管理和开发
浏览量:353056
最新评论
-
Simon.Ezer:
请问对于“如果非主键字段值发生改变,则不会同步过去”这种情况, ...
创建增量同步Oracle物化视图问题 -
dahai639:
挺好的,支持一下
Oracle的pipelined函数实现高性能大数据处理 -
zealotpz:
不错,原来是用户oracle 的所属组的问题
以sysdba身份登录oracle报ORA-1031权限不足错误之完美分析 -
mikixiyou:
zhangyuslam 写道如果担心全局索引失效,可以使用如下 ...
Oracle分区表的分区交互技术实现数据快速转移 -
sea0108:
...
Oracle sql loader使用速成
Oracle Hash join 是一种非常高效的join 算法,主要以CPU(hash计算)和内存空间(创建hash table)为代价获得最大的效率。Hash join一般用于大表和小表之间的连接,我们将小表构建到内存中,称为Hash cluster,大表称为probe表。
当两个表做hash join时,oracle会选择一个表作为驱动表,先根据过滤条件排除不必要的数据,然后将结果集做成hash表,放入进程的hash area,接着扫描第二张表,将记录的join字段值做hash运算,到内存的hash表里面去探测,如果探测成功,就返回数据,否则这行就丢弃掉。
(miki西游 @mikixiyou 原文链接: http://mikixiyou.iteye.com/blog/1709321 )
select /*+use_nl(a b)*/ a.*,b.* from dba_obj a,all_obj b where a.object_id=b.object_id and a.object_name like 'tt%' SELECT STATEMENT, GOAL = ALL_ROWS NESTED LOOPS TABLE ACCESS FULL SCOTT DBA_OBJ TABLE ACCESS BY INDEX ROWID SCOTT ALL_OBJ INDEX UNIQUE SCAN SCOTT PK_ALL_OBJ
执行计划解读
两个表使用了嵌套循环连接。首先访问dba_obj表,得到全部记录。然后按照此表记录依次去扫描all_obj表,扫描过程走索引快速得到all_obj的记录。
select /*+use_hash(a b)*/ a.*,b.* from dba_obj a,all_obj b where a.object_id=b.object_id and a.object_name like 'tt%' SELECT STATEMENT, GOAL = ALL_ROWS HASH JOIN TABLE ACCESS FULL SCOTT DBA_OBJ TABLE ACCESS FULL SCOTT ALL_OBJ
执行计划解读
两个表使用了哈希连接。首先访问dba_obj表,得到全部记录,进行hash运算,放到内存hash area中形成hash table,也称为hash cluster。
然后,再腾出手来,全面扫描all_obj表,每扫描到一条记录时,将join字段进行hash运算,然后到hash area中去找与dba_obj表匹配的记录。
这个行为称为probe,中文称探测。此表也称为probe表。
hash table表是保存在hash area内存区域中,而这个区域在oracle中是分配在pga中。
PGA 包括 进程内存、UGA、sort area,bitmap merge area和hash area。UGA包含session状态信息和private sql area。
使用这个10104 event可以分析hash area的内存分配情况。
alter system set events '10104 trace name context forever,level 2';
select count(*)
from (select /*+use_hash(i g) leading(i)*/
i.*, g.*
from tdividenddetail i, tproductinfo g
where i.c_fundcode = g.fundcode
and i.d_cdate > sysdate - 100);
使用use_hash提示强制让两个表采用hash join关联,然后使用leading提示强制让i表作为驱动表。
在hash area中,默认采用8个partition,每个partition保存若干个 hash table的记录。这些记录又以bucket逻辑结构存储。
分析trc文件内容如下所示:
*** RowSrcId: 1 HASH JOIN STATISTICS (INITIALIZATION) *** Join Type: INNER join Original hash-area size: 3064559 Memory for slot table: 2826240 Calculated overhead for partitions and row/slot managers: 238319 Hash-join fanout: 8 Number of partitions: 8 Number of slots: 23 Multiblock IO: 15 Block size(KB): 8 Cluster (slot) size(KB): 120 Minimum number of bytes per block: 8160 Bit vector memory allocation(KB): 128 Per partition bit vector length(KB): 16 Maximum possible row length: 1708 Estimated build size (KB): 0 Estimated Build Row Length (includes overhead): 408 # Immutable Flags: Not BUFFER(execution) output of the join for PQ Evaluate Left Input Row Vector Evaluate Right Input Row Vector # Mutable Flags: IO sync kxhfSetPhase: phase=BUILD kxhfAddChunk: add chunk 0 (sz=32) to slot table kxhfAddChunk: chunk 0 (lbs=0x2b4b26b47b20, slotTab=0x2b4b26b47ce8) successfuly added kxhfSetPhase: phase=PROBE_1 qerhjFetch: max build row length (mbl=390) *** RowSrcId: 1 END OF BUILD (PHASE 1) *** Revised row length: 370 Revised build size: 9KB kxhfResize(enter): resize to 12 slots (numAlloc=7, max=23) kxhfResize(exit): resized to 12 slots (numAlloc=7, max=12) Slot table resized: old=23 wanted=12 got=12 unload=0 *** RowSrcId: 1 HASH JOIN RESIZE BUILD (PHASE 1) *** Total number of partitions: 8 Number of partitions which could fit in memory: 8 Number of partitions left in memory: 8 Total number of slots in in-memory partitions: 7 kxhfResize(enter): resize to 13 slots (numAlloc=7, max=12) kxhfResize(exit): resized to 13 slots (numAlloc=7, max=13) set work area size to: 1753K (13 slots) *** RowSrcId: 1 HASH JOIN BUILD HASH TABLE (PHASE 1) *** Total number of partitions: 8 Number of partitions left in memory: 8 Total number of rows in in-memory partitions: 27 (used as preliminary number of buckets in hash table) Estimated max # of build rows that can fit in avail memory: 8190 ### Partition Distribution ### Partition:0 rows:3 clusters:1 slots:1 kept=1 Partition:1 rows:5 clusters:1 slots:1 kept=1 Partition:2 rows:3 clusters:1 slots:1 kept=1 Partition:3 rows:4 clusters:1 slots:1 kept=1 Partition:4 rows:6 clusters:1 slots:1 kept=1 Partition:5 rows:3 clusters:1 slots:1 kept=1 Partition:6 rows:3 clusters:1 slots:1 kept=1 Partition:7 rows:0 clusters:0 slots:0 kept=1 Revised number of hash buckets (after flushing): 27 Allocating new hash table. Requested size of hash table: 8 Actual size of hash table: 8 Number of buckets: 64 Match bit vector allocated: FALSE Total number of rows (may have changed): 27 Number of in-memory partitions (may have changed): 8 Final number of hash buckets: 64 Size (in bytes) of hash table: 512 qerhjBuildHashTable(): done hash-table on partition=6, index=1 last_slot#=5 rows=3 total_rows=3 qerhjBuildHashTable(): done hash-table on partition=5, index=2 last_slot#=6 rows=3 total_rows=6 qerhjBuildHashTable(): done hash-table on partition=4, index=3 last_slot#=0 rows=6 total_rows=12 qerhjBuildHashTable(): done hash-table on partition=3, index=4 last_slot#=3 rows=4 total_rows=16 qerhjBuildHashTable(): done hash-table on partition=2, index=5 last_slot#=1 rows=3 total_rows=19 qerhjBuildHashTable(): done hash-table on partition=1, index=6 last_slot#=4 rows=5 total_rows=24 qerhjBuildHashTable(): done hash-table on partition=0, index=7 last_slot#=2 rows=3 total_rows=27 kxhfIterate(end_iterate): numAlloc=7, maxSlots=13 ### Hash table ### # NOTE: The calculated number of rows in non-empty buckets may be smaller # than the true number. Number of buckets with 0 rows: 42 Number of buckets with 1 rows: 18 Number of buckets with 2 rows: 4 Number of buckets with 3 rows: 0 Number of buckets with 4 rows: 0 Number of buckets with 5 rows: 0 Number of buckets with 6 rows: 0 Number of buckets with 7 rows: 0 Number of buckets with 8 rows: 0 Number of buckets with 9 rows: 0 Number of buckets with between 10 and 19 rows: 0 Number of buckets with between 20 and 29 rows: 0 Number of buckets with between 30 and 39 rows: 0 Number of buckets with between 40 and 49 rows: 0 Number of buckets with between 50 and 59 rows: 0 Number of buckets with between 60 and 69 rows: 0 Number of buckets with between 70 and 79 rows: 0 Number of buckets with between 80 and 89 rows: 0 Number of buckets with between 90 and 99 rows: 0 Number of buckets with 100 or more rows: 0 ### Hash table overall statistics ### Total buckets: 64 Empty buckets: 42 Non-empty buckets: 22 Total number of rows: 27 Maximum number of rows in a bucket: 2 Average number of rows in non-empty buckets: 1.227273 *** 2012-10-31 10:37:15.443 qerhjFetch: max probe row length (mpl=0) *** RowSrcId: 1, qerhjFreeSpace(): free hash-join memory kxhfRemoveChunk: remove chunk 0 from slot table
附加:Alibaba DBA Team 关于Oracle hash join 的文档
当做hash join时,oracle会选择一个表作为驱动表,先根据过滤条件排除不必要的数据,然后将结果集做成hash表,放入进程的hash area,接着扫描第二张表,将行的键值做hash运算,到内存的hash表里面去探测,如果探测成功,就返回数据,否则这行就丢弃掉这个是最基本的解释,实际情况中,考虑到单个进程PGA的大小,oracle不会让进程任意的消耗OS内存,hash area是有一定限制的,所以在oracle中,hash也有三种模式:
optimal,onepass,multipass
optimal:当驱动结果集生成的hash表全部可以放入PGA的hash area时,称为optimal,大致过程如下:
1.先根据驱动表,得到驱动结果集
2.在hash area生成hash bulket,并将若干bulket分成一组,成为一个partition,还会生成一个bitmap的列表,每个bulket在上面占一位
3.对结果集的join键做hash运算,将数据分散到相应partition的bulket中,当运算完成后,如果键值唯一性较高的话,bulket里的数据会比较均匀,也有可能有的桶里面数据会是空的,这样bitmap上对应的标志位就是0,有数据的桶,标志位会是1
4.开始扫描第二张表,对jion键做hash运算,确定应该到某个partition的某个bulket去探测,探测之前,会看这个bulket的bitmap是否会1,如果为0,表示没数据,这行就直接丢弃掉
5.如果bitmap为1,则在桶内做精确匹配,判断OK后,返回数据
这个是最优的hash join,他的成本基本是两张表的full table scan,在加微量的hash运算
onepass
如果进程的pga很小,或者驱动表结果集很大,超过了hash area的大小,会怎么办?当然会用到临时表空间,此时oracle的处理方式稍微复杂点需奥注意上面提到的有个partition的概念,可以这么理解,数据是经过两次hash运算的,先确定你的partition,再确定你的bulket,假设hash area小于整个hash table,但至少大于一个partition的size,这个时候走的就是onepass
当我们生成好hash表后,状况是部分partition留在内存中,其他的partition留在磁盘临时表空间中,当然也有可能某个partition一半在内存,一半在磁盘,剩下的步骤大致如下:
1.扫描第二张表,对join键做hash运算,确定好对应的partition和bulket
2.查看bitmap,确定bulket是否有数据,没有则直接丢弃
3.如果有数据,并且这个partition是在内存中的,就进入对应的桶去精确匹配,能匹配上,就返回这行数据,否则丢弃
4.如果partition是在磁盘上的,则将这行数据放入磁盘中暂存起来,保存的形式也是partition,bulket的方式
5.当第二张表被扫描完后,剩下的是驱动表和探测表生成的一大堆partition,保留在磁盘上
6.由于两边的数据都按照相同的hash算法做了partition和bulket,现在只要成对的比较两边partition数据即可,并且在比较的时候,oracle也做了优化处理,没有严格的驱动与被驱动关系,他会在partition对中选较小的一个作为驱动来进行,直到磁盘上所有的partition对都join完
可以发现,相比optimal,他多出的成本是对于无法放入内存的partition,重新读取了一次,所以称为onepass,只要你的内存保证能装下一个partition,oracle都会腾挪空间,每个磁盘partition做到onepass
multipass
这是最复杂,最糟糕的hash join,此时hash area小到连一个partition也容纳不下,当扫描好驱动表后,可能只有半个partition留在hash area中,另半个加其他的partition全在磁盘上,剩下的步骤和onepass比价类似,不同的是针对partition的处理
由于驱动表只有半个partition在内存中,探测表对应的partition数据做探测时,如果匹配不上,这行还不能直接丢弃,需要继续保留到磁盘,和驱动表剩下的半个partition再做join,这里举例的是内存可以装下半个partition,如果装的更少的话,反复join的次数将更多,当发生multipass时,partition物理读的次数会显著增加
发表评论
-
Oracle分区表的分区交互技术实现数据快速转移
2013-01-22 11:48 14808有一个需求,将某业务表的某个时间点之前的记录转移到它的历史 ... -
等待事件enq TX row lock contention分析
2013-01-17 17:16 33295在Oracle数据库性能报告AWRRPT分析时,发现top ... -
Oracle的UNDO表空间管理总结
2013-01-14 15:06 12987UNDO是Oracle中的一个很 ... -
Oracle在不同windows系统中的迁移
2013-01-09 15:41 3806在Windows操作系统环境下 ... -
Oracle 10.2.0.1在windows 2008上安装失败经历
2013-01-07 10:29 8705这两天遇到这个一个项目上的数据库迁移的问题。原来的环境是数据库 ... -
所有的物化视图刷新脚本
2012-12-28 13:59 0select 'execute dbms_mview.refr ... -
Oracle数据库的SQL性能问题分析
2012-12-27 15:31 5289在Oracle 10.2.0.4数据库中,有一个SQL执行缓慢 ... -
db block gets和consistent gets的分析
2012-12-26 18:09 0在Oracle的文档中有这样一段解释: db block g ... -
创建增量同步Oracle物化视图问题
2012-12-25 14:07 15313我们采用Oracle的物化视图增量刷新机制定时将数据库A上的某 ... -
查归档日志文件每小时生成量
2012-12-18 16:13 10792在O racle数据库中,通过v$archived_lo ... -
如何删掉临时表空间的文件
2012-12-18 15:40 0Unlike Oracle datafiles which m ... -
Oracle sql性能诊断暨event 10046和10053使用
2012-12-17 10:24 0早上em grid control监控显示数据库的负载增加,其 ... -
查LOB字段占用的空间大小
2012-12-13 16:00 4579查询Oracle表中LOB字段的占用空间大小。表中每一个LOB ... -
Oracle Data Guard的重做日志传输和应用状况监控
2012-12-04 14:05 4079这是一个用来监控Oracle Data Guard环境下从主库 ... -
Oracle sql loader使用速成
2012-11-30 14:14 4952Oracle SQL LOADER是Oracle的 ... -
Oracle 11g2的监听器配置
2012-11-29 14:34 4391Oracle的监听器服务注册 ... -
Deleting archivelog on physical standby with RMAN in Oracle 10g
2012-11-28 13:25 0Turns out to be quite easy ... -
to_char将number转成string的小技巧
2012-11-27 14:14 10638很多数据转换处理操作时,会遇到将0.007007040000转 ... -
to_date转成字符串时ORA-01843 not a valid month 问题分析
2012-11-26 16:38 29307(注,本文三度易稿) 在开发Oracle SQL或PL/SQL ... -
Data Guard 10g 的保护级别为RESYNCHRONIZATION问题
2012-11-25 11:01 1922Oracle的data guard创建完成 ...
相关推荐
5. 哈希连接(HASH JOIN):自Oracle 7.3引入,哈希连接在处理大数据量时表现优秀。它将一个表的全部数据哈希化,然后与另一个表的数据进行匹配。适合于内部表小,且可以全部装入内存的情况。 6. 索引连接(INDEX ...
哈希连接中,优化器根据统计信息,首先选择两个表中的小表,在内存中建立这张表的基于连接键的哈希表;然后扫描大表,将大表中的数据与哈希表进行比较,如果有相关联则返回结果。 选择合适的连接方式取决于具体的...
本文将深入探讨 Oracle 中的三种主要连接方式:嵌套循环连接(Nested Loop)、排序合并连接(Sort Merge)和哈希连接(Hash Join),并结合案例分析其工作原理和优化策略。 1. 嵌套循环连接(Nested Loop) 嵌套...
### Oracle表的连接方式详解 在Oracle数据库中,表连接是一种常见的操作,用于结合两个或多个表中的数据,以提供更全面的信息。Oracle提供了三种主要的表连接方式:NESTED LOOP JOIN、HASH JOIN和SORT MERGE JOIN。...
5. 散列连接(Hash Join)通过创建内部表的哈希索引,然后对驱动表的每一行进行哈希查找。这种方法适用于处理大规模数据,特别是驱动表较大,且内存资源充足的情况下。 6. 索引连接(Index Join)利用索引来加速...
本文将深入探讨四种常用的表连接方式:嵌套循环连接、排列合并连接、哈希连接以及索引连接,并详细阐述每种连接方式的工作原理、适用场景及其优缺点。 #### 1. 嵌套循环连接(Nested Loop Join) 嵌套循环连接是最...
- 哈希连接(Hash Join):驱动表的数据被哈希化,然后与被驱动表的数据进行匹配,适合处理大数据量的连接。 - 笛卡尔连接(Cross Join):没有连接条件时,每个表的行与另一表的所有行进行组合,通常不推荐使用,...
本文档主要介绍了四种常用的表连接方式:嵌套循环连接、排列合并连接、哈希连接和索引连接。 1. **嵌套循环连接**: - 嵌套循环连接是通过遍历外部表(驱动表)的每一行,并与内部表的每一行进行比较来实现的。...
3. **Oracle连接**:为了连接到Oracle数据库,你需要引用Oracle客户端库,如Oracle Data Provider for .NET (ODP.NET)。安装NuGet包`Oracle.ManagedDataAccess`后,可以使用`OracleConnection`类建立数据库连接。...
Oracle 多表查询优化需要考虑多个方面,包括选择合适的表名顺序、使用 Cache Buffer、语句共享、优化查询路径、避免多表连接查询、优化数据统计、选择合适的索引、优化数据库结构、使用 Materialized View、优化...
临时表空间用于存储数据库操作中的临时数据,如排序操作、哈希和临时表。与永久性表空间不同,临时表空间不会记录在重做日志中,因为这些操作不涉及事务持久性。创建临时表空间的命令通常包括指定表空间名称、临时...
使用哈希表、向量表等数据结构的Java实现,可以明显提高多数据源连接性和可靠性,并对JDBC API函数进行抽象封装,方便开发人员使用。 J2EE架构下的应用服务器 在J2EE架构下,应用服务器为IBM WebSphere ...
自Oracle 7.3版本开始,哈希连接逐渐成为处理表间关联问题的首选策略。 **1. 基本原理** 哈希连接基于等值连接,通过哈希函数将连接对象预先聚集在特定位置。哈希函数并不直接参与连接操作,而是将具有相同哈希值...
- 使用`OracleConnection`类创建数据库连接。实例化时需要提供连接字符串,该字符串包含服务器地址、服务名、用户名和密码等信息。例如:`Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=...
Oracle数据库在处理表之间的连接操作时,提供了三种主要的连接算法:嵌套循环连接(Nested Loop Join)、排序合并连接(Sort Merge Join)和哈希连接(Hash Join)。这些算法各有特点,适用于不同的数据处理场景。 ...
哈希连接创建一个内存中的哈希表,然后对另一个表进行哈希匹配。 - **索引连接(Index-Nested Loop Join)**:利用索引来加速连接,只适用于一个表有唯一索引,且连接条件是该索引的部分或全部。 在数据仓库环境中,...
3. **Oracle数据库**:Oracle是世界上最流行的商业关系型数据库管理系统之一,尤其在企业级应用中广泛使用。在登录程序中,Oracle数据库存储了用户的账户信息,包括用户名和对应的加密密码。 4. **数据库连接池**:...
2. **配置Oracle连接**: - 在服务项目中,配置Oracle数据库连接字符串,这通常在Web.config文件中完成。 - 确保安装了Oracle Client或ODP.NET驱动,以便WCF服务能够与Oracle服务器通信。 3. **创建Oracle数据库...
GUI连接Oracle数据库的实现,为系统带来了高效的数据存储和处理能力。 首先,我们来了解一下GUI。GUI,全称为图形用户界面,它是人与计算机进行交互的主要方式之一。通过图标、按钮、菜单等可视化元素,用户可以...
如果查询涉及多个表,考虑使用连接操作符(JOIN)的优化,如选择合适的JOIN类型和使用外键约束。 工具在优化过程中也扮演着重要角色。例如,"源码"标签可能暗示了我们需要关注应用程序的代码层面。在SQL查询编写时...