oracle怎么走哈希 oracle 哈希連接

oracle什么時候選擇hash join算法

Hash Join只能用于相等連接,且只能在CBO優(yōu)化器模式下。相對于nested loop join,hash join更適合處理大型結果集Hash Join的執(zhí)行計劃第1個是hash表(build table),第2個探查表(probe table),一般不叫內外表,nested loop才有內外表Hash表也就是所謂的內表,探查表所謂的外表

創(chuàng)新互聯(lián)公司-專業(yè)網站定制、快速模板網站建設、高性價比青龍網站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式青龍網站制作公司更省心,省錢,快速模板網站建設找我們,業(yè)務覆蓋青龍地區(qū)。費用合理售后完善,十載實體公司更值得信賴。

兩者的執(zhí)行計劃形如:

nested loop

outer table --驅動表

inner table

hash join

build table (inner table) --驅動表

probe table (outer table)

先看一張圖片,大致了解Hash Join的過程:

深入理解Oracle表:三大表連接方式詳解之Hash Join的定義,原理,算法,成本,模式和位圖 - Andy - Andys home下面詳細了解一下Hash Join

一 Hash join概念

Hash join算法的一個基本思想就是根據(jù)小的row sources(稱作build input 也就是前文提到的build table,我們記較小的表為S,較大的表為B)建立一個可以存在于hash area內存中的hash table然后用大的row sources(稱作probe input,也就是前文提到的probe table) 來探測前面所建的hash table如果hash area內存不夠大,hash table就無法完全存放在hash area內存中針對這種情況,Oracle在連接鍵利用一個hash函數(shù)將build input和probe input分割成多個不相連的分區(qū)分別記作Si和Bi,這個階段叫做分區(qū)階段;然后各自相應的分區(qū),即Si和Bi再做Hash join,這個階段叫做join階段如果HASH表太大,無法一次構造在內存中,則分成若干個partition,寫入磁盤的temporary segment,則會多一個寫的代價,會降低效率至于小表的概念,對于 hash join 來說,能容納在 pga 中的 hash table 都可以叫小表,通常比如:

pga_aggregate_target big integer 1073741824hash area size 大體能使用到40多 M ,這樣的話通常可能容納 幾十萬的記錄hash area size缺省是2*sort_area_size,我們可以直接修改SORT_AREA_SIZE 的大小,HASH_AREA_SIZE也會跟著改變的如果你的workarea_size_policy=auto,那么我們只需設定pga_aggregate_target但請記住,這是一個session級別的參數(shù),有時,我們更傾向于把hash_area_size的大小設成驅動表的1.6倍左右驅動表僅僅用于nested loop join 和 hash join,但Hash join不需要在驅動表上存在索引,而nested loop join則迫切需求一兩百萬記錄的表 join上 千萬記錄的表,hash join的通常表現(xiàn)非常好不過,多與少,大與小,很多時候很難量化,具體情況還得具體分析如果在分區(qū)后,針對某個分區(qū)所建的hash table還是太大的話,oracle就采用nested loop hash join所謂的nested-loops hash join就是對部分Si建立hash table,然后讀取所有的Bi與所建的hash table做連接然后再對剩余的Si建立hash table,再將所有的Bi與所建的hash table做連接,直至所有的Si都連接完了二 Hash Join原理

考慮以下兩個數(shù)據(jù)集:

S={1,1,1,3,3,4,4,4,4,5,8,8,8,8,10}

B={0,0,1,1,1,1,2,2,2,2,2,2,3,8,9,9,9,10,10,11}

Hash Join的第一步就是判定小表(即build input)是否能完全存放在hash area內存中如果能完全存放在內存中,則在內存中建立hash table,這是最簡單的hash join如果不能全部存放在內存中,則build input必須分區(qū)。分區(qū)的個數(shù)叫做fan-outFan-out是由hash_area_size和cluster size來決定的。其中cluster size等于db_block_size * _hash_multiblock_io_counthash_multiblock_io_count是個隱藏參數(shù),在9.0.1以后就不再使用了[sql]

sys@ORCL ed

Wrote file afiedt.buf

1 select a.ksppinm name,b.ksppstvl value,a.ksppdesc description2 from x$ksppi a,x$ksppcv b

3 where a.indx = b.indx

4* and a.ksppinm like '%hash_multiblock_io_count%'

sys@ORCL /

NAME VALUE DESCRIPTION

------------------------------ ----- ------------------------------------------------------------_hash_multiblock_io_count 0 number of blocks hash join will read/write at onceOracle采用內部一個hash函數(shù)作用于連接鍵上,將S和B分割成多個分區(qū)在這里我們假設這個hash函數(shù)為求余函數(shù),即Mod(join_column_value,10)這樣產生十個分區(qū),如下表:

深入理解Oracle表:三大表連接方式詳解之Hash Join的定義,原理,算法,成本,模式和位圖 - Andy - Andys home經過這樣的分區(qū)之后,只需要相應的分區(qū)之間做join即可(也就是所謂的partition pairs)如果有一個分區(qū)為NULL的話,則相應的分區(qū)join即可忽略在將S表讀入內存分區(qū)時,oracle即記錄連接鍵的唯一值,構建成所謂的位圖向量它需要占hash area內存的5%左右。在這里即為{1,3,4,5,8,10}

當對B表進行分區(qū)時,將每一個連接鍵上的值與位圖向量相比較,如果不在其中,則將其記錄丟棄在我們這個例子中,B表中以下數(shù)據(jù)將被丟棄{0,0,2,2,2,2,2,2,9,9,9,9,9}

這個過程就是位圖向量過濾

當S1,B1做完連接后,接著對Si,Bi進行連接

這里oracle將比較兩個分區(qū),選取小的那個做build input,就是動態(tài)角色互換這個動態(tài)角色互換發(fā)生在除第一對分區(qū)以外的分區(qū)上面三 Hash Join算法

第1步:判定小表是否能夠全部存放在hash area內存中,如果可以,則做內存hash join。如果不行,轉第二步第2步:決定fan-out數(shù)

(Number of Partitions) * C= Favm *M

其中C為Cluster size,其值為DB_BLOCK_SIZE*HASH_MULTIBLOCK_IO_COUNTFavm為hash area內存可以使用的百分比,一般為0.8左右M為Hash_area_size的大小

第3步:讀取部分小表S,采用內部hash函數(shù)(這里稱為hash_fun_1)將連接鍵值映射至某個分區(qū),同時采用hash_fun_2函數(shù)對連接鍵值產生另外一個hash值這個hash值用于創(chuàng)建hash table用,并且與連接鍵值存放在一起第4步:對build input建立位圖向量

第5步:如果內存中沒有空間了,則將分區(qū)寫至磁盤上第6步:讀取小表S的剩余部分,重復第三步,直至小表S全部讀完第7步:將分區(qū)按大小排序,選取幾個分區(qū)建立hash table(這里選取分區(qū)的原則是使選取的數(shù)量最多)第8步:根據(jù)前面用hash_fun_2函數(shù)計算好的hash值,建立hash table第9步:讀取表B,采用位圖向量進行位圖向量過濾第10步:對通過過濾的數(shù)據(jù)采用hash_fun_1函數(shù)將數(shù)據(jù)映射到相應的分區(qū)中去,并計算hash_fun_2的hash值第11步:如果所落的分區(qū)在內存中,則將前面通過hash_fun_2函數(shù)計算所得的hash值與內存中已存在的hash table做連接將結果寫致磁盤上。如果所落的分區(qū)不在內存中,則將相應的值與表S相應的分區(qū)放在一起第12步:繼續(xù)讀取表B,重復第9步,直至表B讀取完畢第13步:讀取相應的(Si,Bi)做hash連接。在這里會發(fā)生動態(tài)角色互換第14步:如果分區(qū)過后,最小的分區(qū)也比內存大,則發(fā)生nested-loop hash join四 Hash Join的成本

⑴ In-Memory Hash Join

Cost(HJ)=Read(S)+ build hash table in memory(CPU)+Read(B) + Perform In memory Join(CPU)忽略cpu的時間,則:

Cost(HJ)=Read(S)+Read(B)

⑵ On-Disk Hash Join

根據(jù)上述的步驟描述,我們可以看出:

Cost(HJ)=Cost(HJ1)+Cost(HJ2)

其中Cost(HJ1)的成本就是掃描S,B表,并將無法放在內存上的部分寫回磁盤,對應前面第2步至第12步Cost(HJ2)即為做nested-loop hash join的成本,對應前面的第13步至第14步其中Cost(HJ1)近似等于Read(S)+Read(B)+Write((S-M)+(B-B*M/S))因為在做nested-loop hash join時,對每一chunk的build input,都需要讀取整個probe input,因此Cost(HJ2)近似等于Read((S-M)+n*(B-B*M/S)),其中n是nested-loop hash join需要循環(huán)的次數(shù):n=(S/F)/M一般情況下,如果n大于10的話,hash join的性能將大大下降從n的計算公式可以看出,n與Fan-out成反比例,提高fan-out,可以降低n當hash_area_size是固定時,可以降低cluster size來提高fan-out從這里我們可以看出,提高hash_multiblock_io_count參數(shù)的值并不一定提高hash join的性能五 Hash Join的過程

一次完整的hash join如下:

1 計算小表的分區(qū)(bucket)數(shù)--Hash分桶

決定hash join的一個重要因素是小表的分區(qū)(bucket)數(shù)這個數(shù)字由hash_area_size、hash_multiblock_io_count和db_block_size參數(shù)共同決定Oracle會保留hash area的20%來存儲分區(qū)的頭信息、hash位圖信息和hash表因此,這個數(shù)字的計算公式是:

Bucket數(shù)=0.8*hash_area_size/(hash_multiblock_io_count*db_block_size)2 Hash計算

讀取小表數(shù)據(jù)(簡稱為R),并對每一條數(shù)據(jù)根據(jù)hash算法進行計算Oracle采用兩種hash算法進行計算,計算出能達到最快速度的hash值(第一hash值和第二hash值)而關于這些分區(qū)的全部hash值(第一hash值)就成為hash表3 存放數(shù)據(jù)到hash內存中

將經過hash算法計算的數(shù)據(jù),根據(jù)各個bucket的hash值(第一hash值)分別放入相應的bucket中第二hash值就存放在各條記錄中

4 創(chuàng)建hash位圖

與此同時,也創(chuàng)建了一個關于這兩個hash值映射關系的hash位圖5 超出內存大小部分被移到磁盤

如果hash area被占滿,那最大一個分區(qū)就會被寫到磁盤(臨時表空間)上去任何需要寫入到磁盤分區(qū)上的記錄都會導致磁盤分區(qū)被更新這樣的話,就會嚴重影響性能,因此一定要盡量避免這種情況2-5一直持續(xù)到整個表的數(shù)據(jù)讀取完畢

6 對分區(qū)排序

為了能充分利用內存,盡量存儲更多的分區(qū),Oracle會按照各個分區(qū)的大小將他們在內存中排序7 讀取大表數(shù)據(jù),進行hash匹配

接下來就開始讀取大表(簡稱S)中的數(shù)據(jù)

按順序每讀取一條記錄,計算它的hash值,并檢查是否與內存中的分區(qū)的hash值一致如果是,返回join數(shù)據(jù)

如果內存中的分區(qū)沒有符合的,就將S中的數(shù)據(jù)寫入到一個新的分區(qū)中,這個分區(qū)也采用與計算R一樣的算法計算出hash值也就是說這些S中的數(shù)據(jù)產生的新的分區(qū)數(shù)應該和R的分區(qū)集的分區(qū)數(shù)一樣。這些新的分區(qū)被存儲在磁盤(臨時表空間)上8 完全大表全部數(shù)據(jù)的讀取

一直按照7進行,直到大表中的所有數(shù)據(jù)的讀取完畢9 處理沒有join的數(shù)據(jù)

這個時候就產生了一大堆join好的數(shù)據(jù)和從R和S中計算存儲在磁盤上的分區(qū)10 二次hash計算

從R和S的分區(qū)集中抽取出最小的一個分區(qū),使用第二種hash函數(shù)計算出并在內存中創(chuàng)建hash表采用第二種hash函數(shù)的原因是為了使數(shù)據(jù)分布性更好11 二次hash匹配

在從另一個數(shù)據(jù)源(與hash在內存的那個分區(qū)所屬數(shù)據(jù)源不同的)中讀取分區(qū)數(shù)據(jù),與內存中的新hash表進行匹配。返回join數(shù)據(jù)12 完成全部hash join

繼續(xù)按照9-11處理剩余分區(qū),直到全部處理完畢六 Hash Join的模式

Oracle中,Hash Join也有三種模式:optimal,one-pass,multi-pass⑴ optimal

當驅動結果集生成的hash表全部可以放入PGA的hash area時,稱為optimal,大致過程如下:

① 先根據(jù)驅動表,得到驅動結果集

② 在hash area生成hash bulket,并將若干bulket分成一組,成為一個partition,還會生成一個bitmap的列表,每個bulket在上面占一位③ 對結果集的join鍵做hash運算,將數(shù)據(jù)分散到相應partition的bulket中當運算完成后,如果鍵值唯一性較高的話,bulket里的數(shù)據(jù)會比較均勻,也有可能有的桶里面數(shù)據(jù)會是空的這樣bitmap上對應的標志位就是0,有數(shù)據(jù)的桶,標志位會是1④ 開始掃描第二張表,對jion鍵做hash運算,確定應該到某個partition的某個bulket去探測探測之前,會看這個bulket的bitmap是否會1,如果為0,表示沒數(shù)據(jù),這行就直接丟棄掉⑤ 如果bitmap為1,則在桶內做精確匹配,判斷OK后,返回數(shù)據(jù)這個是最優(yōu)的hash join,他的成本基本是兩張表的full table scan,在加微量的hash運算博客開篇的那幅圖描述的也就是這種情況

⑵ one-pass

如果進程的pga很小,或者驅動表結果集很大,超過了hash area的大小,會怎么辦?

當然會用到臨時表空間,此時oracle的處理方式稍微復雜點需奧注意上面提到的有個partition的概念可以這么理解,數(shù)據(jù)是經過兩次hash運算的,先確定你的partition,再確定你的bulket假設hash area小于整個hash table,但至少大于一個partition的size,這個時候走的就是one-pass當我們生成好hash表后,狀況是部分partition留在內存中,其他的partition留在磁盤臨時表空間中當然也有可能某個partition一半在內存,一半在磁盤,剩下的步驟大致如下:

① 掃描第二張表,對join鍵做hash運算,確定好對應的partition和bulket② 查看bitmap,確定bulket是否有數(shù)據(jù),沒有則直接丟棄③ 如果有數(shù)據(jù),并且這個partition是在內存中的,就進入對應的桶去精確匹配,能匹配上,就返回這行數(shù)據(jù),否則丟棄④ 如果partition是在磁盤上的,則將這行數(shù)據(jù)放入磁盤中暫存起來,保存的形式也是partition,bulket的方式⑤ 當?shù)诙埍肀粧呙柰旰螅O碌氖球寗颖砗吞綔y表生成的一大堆partition,保留在磁盤上⑥ 由于兩邊的數(shù)據(jù)都按照相同的hash算法做了partition和bulket,現(xiàn)在只要成對的比較兩邊partition數(shù)據(jù)即可并且在比較的時候,oracle也做了優(yōu)化處理,沒有嚴格的驅動與被驅動關系他會在partition對中選較小的一個作為驅動來進行,直到磁盤上所有的partition對都join完可以發(fā)現(xiàn),相比optimal,他多出的成本是對于無法放入內存的partition,重新讀取了一次,所以稱為one-pass只要你的內存保證能裝下一個partition,oracle都會騰挪空間,每個磁盤partition做到one-pass⑶ multi-pass

這是最復雜,最糟糕的hash join

此時hash area小到連一個partition也容納不下,當掃描好驅動表后可能只有半個partition留在hash area中,另半個加其他的partition全在磁盤上剩下的步驟和one-pass比價類似,不同的是針對partition的處理由于驅動表只有半個partition在內存中,探測表對應的partition數(shù)據(jù)做探測時如果匹配不上,這行還不能直接丟棄,需要繼續(xù)保留到磁盤,和驅動表剩下的半個partition再做join這里舉例的是內存可以裝下半個partition,如果裝的更少的話,反復join的次數(shù)將更多當發(fā)生multi-pass時,partition物理讀的次數(shù)會顯著增加七 Hash Join的位圖

這個位圖包含了每個hash分區(qū)是否有有值的信息。它記錄了有數(shù)據(jù)的分區(qū)的hash值這個位圖的最大作用就是,如果probe input中的數(shù)據(jù)沒有與內存中的hash表匹配上先查看這個位圖,以決定是否將沒有匹配的數(shù)據(jù)寫入磁盤那些不可能匹配到的數(shù)據(jù)(即位圖上對應的分區(qū)沒有數(shù)據(jù))就不再寫入磁盤八 小結

① 確認小表是驅動表

② 確認涉及到的表和連接鍵分析過了

③ 如果在連接鍵上數(shù)據(jù)不均勻的話,建議做柱狀圖④ 如果可以,調大hash_area_size的大小或pga_aggregate_target的值⑤ Hash Join適合于小表與大表連接、返回大型結果集的連接

oracle 怎么使用哈希鏈接

對于排序合并連接,如果兩個表在施加了目標SQL中指定的謂詞條件后得到的結果集很大而且需要排序,則排序合并連接的執(zhí)行效率一定不高;

而對于嵌套循環(huán)連接,如果驅動表所對應的驅動結果集的記錄數(shù)很大,即便在被驅動表的連接列上存在索引,此時使用嵌套循環(huán)連接的執(zhí)行效率也會同樣不高。

為了解決這個問題,于是Oracle引進了哈希連接。在ORACLE 10g及其以后的版本中,優(yōu)化器 (實際上是CBO,因為哈希連接僅適用于CBO)在解析目標SQL的時候是否考慮哈希連接受限于隱含參數(shù)_HASH_JOIN_ENABLED,默認值是TRUE.

oracle hash join 怎么用

hash join是一種連接方式,一般用在等值連接,oracle會根據(jù)具體的成本選擇是否使用這種連接方式。如果一定要使用hash join可以家hint使用,具體的hint寫法忘記了,自己查查吧。好象是/*+hash+*/

如果大表和小表的連接,一般會用nested loop連接方式。自查詢的in等連接方式一般也是這種選擇方式。

oracle的執(zhí)行計劃中表的鏈接方式有幾種?分別適用什么情況?

在日?;跀?shù)據(jù)庫應用的開發(fā)過程中,我們經常需要對多個表或者數(shù)據(jù)源進行關聯(lián)查詢而得出我們需要的結果集。那么Oracle到底存在著哪幾種連接方式?優(yōu)化器內部又是怎樣處理這些連接的?哪種連接方式又是適合哪種查詢需求的?只有對這些問題有了清晰的理解后,我們才能針對特定的查詢需求選擇合適的連接方式,開發(fā)出健壯的數(shù)據(jù)庫應用程序。選擇合適的表連接方法對SQL語句運行的性能有著至關重要的影響。下面我們就Oracle常用的一些連接方法及適用情景做一個簡單的介紹。

3.1 嵌套循環(huán)連接(nested loop)

嵌套循環(huán)連接的工作方式是這樣的:

1、 Oracle首先選擇一張表作為連接的驅動表,這張表也稱為外部表(Outer Table)。由驅動表進行驅動連接的表或數(shù)據(jù)源稱為內部表(Inner Table)。

2、 提取驅動表中符合條件的記錄,與被驅動表的連接列進行關聯(lián)查詢符合條件的記錄。在這個過程中,Oracle首先提取驅動表中符合條件的第一條記錄,再與內部表的連接列進行關聯(lián)查詢相應的記錄行。在關聯(lián)查詢的過程中,Oracle會持續(xù)提取驅動表中其他符合條件的記錄與內部表關聯(lián)查詢。這兩個過程是并行進行的,因此嵌套循環(huán)連接返回前幾條記錄的速度是非??斓?。在這里需要說明的是,由于Oracle最小的IO單位為單個數(shù)據(jù)塊,因此在這個過程中Oracle會首先提取驅動表中符合條件的單個數(shù)據(jù)塊中的所有行,再與內部表進行關聯(lián)連接查詢的,然后提取下一個數(shù)據(jù)塊中的記錄持續(xù)地循環(huán)連接下去。當然,如果單行記錄跨越多個數(shù)據(jù)塊的話,就是一次單條記錄進行關聯(lián)查詢的。

3、 嵌套循環(huán)連接的過程如下所示:

Nested loop

Outer loop

Inner loop

我們可以看出這里面存在著兩個循環(huán),一個是外部循環(huán),提取驅動表中符合條件的每條記錄。另外一個是內部循環(huán),根據(jù)外循環(huán)中提取的每條記錄對內部表進行連接查詢相應的記錄。由于這兩個循環(huán)是嵌套進行的,故此種連接方法稱為嵌套循環(huán)連接。

嵌套循環(huán)連接適用于查詢的選擇性強、約束性高并且僅返回小部分記錄的結果集。通常要求驅動表的記錄(符合條件的記錄,通常通過高效的索引訪問)較少,且被驅動表連接列有唯一索引或者選擇性強的非唯一索引時,嵌套循環(huán)連接的效率是比較高的。

嵌套循環(huán)連接驅動表的選擇也是連接中需要著重注意的一點,有一個常見的誤區(qū)是驅動表要選擇小表,其實這是不對的。假如有兩張表A、B關聯(lián)查詢,A表有1000000條記錄,B表有10000條記錄,但是A表過濾出來的記錄只有10條,這時候顯然用A表當做驅動表是比較合適的。因此驅動表是由過濾條件限制返回記錄最少的那張表,而不是根據(jù)表的大小來選擇的。

在外連接查詢中,如果走嵌套循環(huán)連接的話,那么驅動表必然是沒有符合條件關聯(lián)的那張表,也就是后面不加(+)的那張表。這是由于外連接需要提取可能另一張表沒符合條件的記錄,因此驅動表需要是那張我們要返回所有符合條件記錄的表。比如下面這個查詢,

嵌套循環(huán)連接返回前幾行的記錄是非??斓模@是因為使用了嵌套循環(huán)后,不需要等到全部循環(huán)結束再返回結果集,而是不斷地將查詢出來的結果集返回。在這種情況下,終端用戶將會快速地得到返回的首批記錄,且同時等待Oracle內部處理其他記錄并返回。如果查詢的驅動表的記錄數(shù)非常多,或者被驅動表的連接列上無索引或索引不是高度可選的情況,嵌套循環(huán)連接的效率是非常低的

-- 刪除原表

drop table t1;

-- 建立測試表

create table t1(

f1 varchar2(10),

f2 varchar2(1000)

)

tablespace CTL

pctfree 98;

-- 填充測試內容

insert into t1(f1,f2)

select rownum, lpad(rownum,700,'0')

from dba_tables a, dba_tab_cols b

where a.owner = b.owner

and rownum 10000;

commit;

-- 檢查測試內容格式

select sys.dbms_rowid.rowid_block_number(rowid), f1, f2 from t1;

-- 每條記錄都存儲在單獨的數(shù)據(jù)塊中

select count( distinct sys.dbms_rowid.rowid_block_number(rowid)) from t1;

/*

用同樣的方式建立表t2

*/

-- 刪除原表

drop table t2;

-- 建立測試表

create table t2(

f1 varchar2(10),

f2 varchar2(1000)

)

tablespace CTL

pctfree 98;

-- 填充測試內容

insert into t2(f1,f2)

select rownum * 10, lpad(rownum * 10,700,'0')

from dba_tables a, dba_tab_cols b

where a.owner = b.owner

and rownum 1000;

commit;

-- 檢查測試內容格式

select sys.dbms_rowid.rowid_block_number(rowid), f1, f2 from t2;

-- 每條記錄都存儲在單獨的數(shù)據(jù)塊中

select count( distinct sys.dbms_rowid.rowid_block_number(rowid)) from t2;

create index ind_t1_f1 on t1(f1);

create index ind_t2_f1 on t2(f1);

--首先我們來看使用nested loop關聯(lián)方式, 不同表作為驅動時的情況.

1, 表t2作為驅動表

select /*+ ordered use_nl(t1 , t2)*/

t1.f1, t2.f1

from ctl.t2 t2,ctl.t1 t1

where t1.f1 = t2.f1

and t1.f1 1000;

Execution Plan

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

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=84 Card=4 Bytes=56)

1 0 NESTED LOOPS (Cost=84 Card=4 Bytes=56)

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

3 1 INDEX (RANGE SCAN) OF 'IND_T1_F1' (NON-UNIQUE) (Cost=1 C

ard=1 Bytes=7)

Cost = outer access cost + (inner access cost * outer cardinality)

Cost = 2 + 1 * 82 = 84;

Statistics

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

0 recursive calls

0 db block gets

2020 consistent gets

23 physical reads

0 redo size

2650 bytes sent via SQL*Net to client

721 bytes received via SQL*Net from client

8 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

99 rows processed

2, t1作為驅動表

Execution Plan

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

0 SELECT STATEMENT Optimizer=CHOOSE (Cost=6 Card=4 Bytes=56)

1 0 NESTED LOOPS (Cost=6 Card=4 Bytes=56)

2 1 TABLE ACCESS (FULL) OF 'T1' (Cost=2 Card=4 Bytes=28)

3 1 INDEX (RANGE SCAN) OF 'IND_T2_F1' (NON-UNIQUE) (Cost=1 C

ard=1 Bytes=7)

Cost = outer access cost + (inner access cost * outer cardinality)

Cost = 2 + 1 * 4 = 84;

Statistics

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

0 recursive calls

0 db block gets

11123 consistent gets

3 physical reads

0 redo size

2650 bytes sent via SQL*Net to client

721 bytes received via SQL*Net from client

8 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

99 rows processed

3.2, 哈希連接(hash join)

哈希連接分為兩個階段,如下。

1、 構建階段:優(yōu)化器首先選擇一張小表做為驅動表,運用哈希函數(shù)對連接列進行計算產生一張哈希表。通常這個步驟是在內存(hash_area_size)里面進行的,因此運算很快。

2、 探測階段:優(yōu)化器對被驅動表的連接列運用同樣的哈希函數(shù)計算得到的結果與前面形成的哈希表進行探測返回符合條件的記錄。這個階段中如果被驅動表的連接列的值沒有與驅動表連接列的值相等的話,那么這些記錄將會被丟棄而不進行探測

哈希連接比較適用于返回大數(shù)據(jù)量結果集的連接。

使用哈希連接必須是在CBO模式下,參數(shù)hash_join_enabled設置為true,

哈希連接只適用于等值連接。從Oracle9i開始,哈希連接由于其良好的性能漸漸取代了原來的排序合并連接。

SQL select /*+ ordered use_hash(t1 , t2) */

t1.f1, t2.f1

from ctl.t1 t1,ctl.t2 t2

where t1.f1 = t2.f1 2 3 4 ;

999 rows selected.

Execution Plan

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

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

)

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

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

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

Statistics

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

0 recursive calls

0 db block gets

11113 consistent gets

0 physical reads

0 redo size

23590 bytes sent via SQL*Net to client

1381 bytes received via SQL*Net from client

68 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

999 rows processed

3.3, 排序合并連接(merge join)

排序合并連接的方法非常簡單。在排序合并連接中是沒有驅動表的概念的,兩個互相連接的表按連接列的值先排序,排序完后形成的結果集再互相進行合并連接提取符合條件的記錄。相比嵌套循環(huán)連接,排序合并連接比較適用于返回大數(shù)據(jù)量的結果。

排序合并連接在數(shù)據(jù)表預先排序好的情況下效率是非常高的,也比較適用于非等值連接的情況,比如、=、=等情況下的連接(哈希連接只適用于等值連接)。由于Oracle中排序操作的開銷是非常消耗資源的,當結果集很大時排序合并連接的性能很差,于是Oracle在7.3之后推出了新的連接方式——哈希連接。

1, rbo模式;

2, 不等于關聯(lián)( = = )

3, hash_join_enabled = false;

4, 數(shù)據(jù)源已排序

oracle11g hash 分區(qū) 索引怎么用

oracle11g hash 分區(qū) 索引怎么用

Hash Global分區(qū)索引介紹

HASH-Partitioned Global索引是Oracle 10g開始提供的新特性。而在以前的版本中

,Oracle只支持Range-Partitioned Global索引。HASH-Partitioned Global索引的好處如下:

比Range-Partitioned Global索引易于實施。HASH-Partitioned Global索引是根據(jù)

索引字段值,通過Oracle內部的HASH算法自動均勻散列到定義的分區(qū)中。而

Range-Partitioned Global索引需要根據(jù)索引字段值的范圍進行分區(qū),因此實施和

維護的難度都大。

當前標題:oracle怎么走哈希 oracle 哈希連接
分享網址:http://muchs.cn/article36/hjcosg.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供移動網站建設、營銷型網站建設做網站、商城網站、網站導航、網站排名

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網站建設