日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Oracle表连接深入浅出

發布時間:2024/4/15 编程问答 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle表连接深入浅出 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

表的連接

表的連接是指在一個SQL語句中通過表與表之間的關聯,從一個或多個表檢索出相關的數據。如果一個SQL語句的關聯表超過兩個,

那么連接的順序如何呢?ORACLE首先連接其中的兩個表,產生一個結果集;然后將產生的結果集與下一個表再進行關聯;繼續這

個過程,直到所有的表都連接完成;最后產生所需的數據。

ORACLE 從6的版本開始,優化器使用4種不同的表的連接方式:

?

1 嵌套循環連接(NESTED LOOP JOIN)

2 群集連接 (CLUSTER JOIN)

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

4 笛卡爾連接 (CARTESIAN JOIN)

ORACLE 7.3中,新增加了

5 哈希連接(HASH JOIN)。

在ORACLE 8中,新增加了

6 索引連接(INDEX JOIN)。

這六種連接方式都有其各自技術特點,在一定的條件下,可以充分發揮高效的性能。但是也都有其局限性,如果使用不當,不僅不

能提高效率,反而會嚴重影響系統的性能。因此,深入地探討連接方式的內部 運行機制對于性能優化是必要的。

1 嵌套循環連接

嵌套循環連接的內部處理的流程:

1) Oracle 優化器根據基于規則RBO或基于成本CBO的原則,選擇兩個表中的一個作為驅動表,并指定其為外部表。

2) Oracle 優化器再將另外一個表指定為內部表。

3) Oracle從外部表中讀取第一行,然后和內部表中的數據逐一進行對比,所有匹配的記錄放在結果集中。

4) Oracle讀取外部表中的第二行,再和內部表中的數據逐一進行對比,所有匹配的記錄添加到結果集中。

5) 重復上述步驟,直到外部表中的所有紀錄全部處理完。

6) 最后產生滿足要求的結果集。

使用嵌套循環連接是一種從結果集中提取第一批記錄最快速的方法。在驅動行源表(就是正在查找的記錄,外部表)較小、或者內部行

源表已連接的列有惟一的索引或高度可選的非惟一索引時, 嵌套循環連接效果是比較理想的。嵌套循環連接比其他連接方法有優勢,它

可以快速地從結果集中提取第一批記錄,而不用等待整個結果集完全確定下來。這樣,在理想情況下,終端用戶就可以通過查詢屏幕查看

第一批記錄,而在同時讀取其他記錄。不管如何定義連接的條件或者模式,任何兩個行記錄源都可以使用嵌套循環連接,所以嵌套循環連

接是非常靈活的。

然而,

如果內部行源表(讀取的第二張表)已連接的列上不包含索引,或者索引不是高度可選時,嵌套循環連接效率是很低的。

如果驅動表的記錄非常龐大時,其他的連接方法可能更加有效。

可以通過在SQL語句中添加HINTS(use_nl),強制ORACLE優化器產生嵌套循環連接的執行計劃。


2 群集連接(CLUSTER JOIN)

群集連接實際上是嵌套循環連接的一種特例。如果所連接的兩張源表是群集中的表,即兩張表屬于同一個段(SEGMENT),

那么ORACLE能夠使用群集連接。處理的過程是:ORACLE從第一張行源表中讀取第一行,然后在第二張行源表中使用CLUSTER索

引查找能夠匹配到的紀錄;繼續上面的步驟處理行源表中的第二行,直到所有的記錄全部處理完。

?

群集連接的效率極高,因為兩個參加連接的行源表實際上處于同一個物理塊上。但是,群集連接也有其限制,沒有群集的兩

個表不可能用群集連接。所以,群集連接實際上很少使用。

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

排序合并連接內部處理的流程:

1) 優化器判斷第一個行源表是否已經排序,如果已經排序,則到第3步,否則到第2步。

2) 第一個源表排序

3) 優化器判斷第二個行源表是否已經排序,如果已經排序,則到第5步,否則到第4步。

4) 第二個源表排序

5) 已經排過序的兩個源表進行合并操作,并生成最終的結果集。

在缺乏數據的選擇性或者可用的索引時,或者兩個行源表都過于龐大(所選的數據超過表記錄數的5%)時,排序合并連接將比嵌套

循環連更加高效。排列合并連接需要比較大的臨時內存塊,以用于排序,這將導致在臨時表空間占用更多的內存和磁盤I/O。

可以通過在SQL語句中添加HINTS(use_merge),強制ORACLE優化器產生排序合并連接的執行計劃。

4 笛卡爾連接 (CARTESIAN JOIN)

笛卡爾連接是指在sql語句中沒有寫出表連接的條件,優化器把第一個表的每一條記錄和第二個表的所有紀錄相連接。如果第

一個表的紀錄數為m, 第二個表的紀錄數為m,則會產生m*n條紀錄數。

由于笛卡爾連接會導致性能很差的SQL,因此一般也很少用到。

5 哈希連接(Hash Join)

Hash Join 概述

Hash join 算法的一個基本思想就是根據小的row sources(稱作build input我們記較小的表為S ,較大的表為B)建立一個可以

存在于 hash area內存中的hash table ,然后用大的 row sources(稱作probe input) 來探測前面所建的hash table。如果

hash area 內存不夠大, hash table就無法完全存放在hash area內存中。針對這種情況,Oracle在連接鍵利用一個hash函數將

build input 和 probe input 分割成多個不相連的分區(分別記作 Si 和 Bi ),這個階段叫做分區階段;然后各自相應的分區,

即 Si 和 Bi 再做 Hash join ,這個階段叫做 join 階段。

如果在分區后,針對某個分區所建的hash table還是太大的話,oracle就采用nested-loops hash join. 所謂的nested-loops hash join就是對部分 Si 建立 hash table ,然后讀取所有的 Bi 與所建的 hash table 做連接,然后再對剩余的 Si 建立 hash table ,再

將所有的 Bi 與所建的 hash table 做連接,直至所有的 Si 都連接完了。

Hash Join 算法有一個限制,就是它是在假設兩張表在連接鍵上是均勻的,也就是說每個分區擁有差不多的數據。但是實際當中數據都是不

均勻的,為了很好地解決這個問題, oracle 引進了幾種技術,位圖向量過濾、角色互換、柱狀圖,這些術語的具體意義會在后面詳細介紹。



Hash Join 原理

我們用一個例子來解釋 Hash Join 算法的原理,以及上述所提到的術語。

考慮以下兩個數據集。

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}

oracle優化器根據統計信息,Hash Join 的第一步就是判定小表(即 build input )是否能完全存放在 hash area 內存中。如果能完全存放在內存中,則在內存中建立 hash table ,這是最簡單的 hash join 。

?

如果不能全部存放在內存中,則 build input 必須分區。分區的個數叫做 fan-out 。 Fan-out 是由 hash_area_size 和 cluster size 來決定的。其中 cluster size 等于 db_block_size * hash_multiblock_io_count , hash_multiblock_io_count 在 oracle9i 中是隱含參數。這里需要注意的是 fan-out 并不是 build input 的大小 /hash_ara_size ,也就是說 oracle 決定的分區大小有可能還是不能完全存放在 hash area 內存中。大的 fan-out 導致許多小的分區,影響性能,而小的 fan-out 導致少數的大的分區,以至于每個分區不能全部存放在內存中,這也影響 hash join 的性能。

Oracle 采用內部一個 hash 函數作用于連接鍵上,將 S 和 B 分割成多個分區,在這里我們假設這個 hash 函數為求余函數,即 Mod(join_column_value,10) 。這樣產生十個分區,如下表。

經過這樣的分區之后,只需要相應的分區之間做 join 即可(也就是所謂的 partition pairs ),如果有一個分區為 NULL 的話,則相應的分區 join 即可忽略。

在將 S 表讀入內存分區時,oracle將記錄連接鍵的唯一值,構建成所謂的位圖向量,它需要占 hash area 內存的 5% 左右。在這里即為 {1,3,4,5,8,10} 。

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

當 S1,B1 做完連接后,接著對 Si,Bi 進行連接,這里 oracle 將比較兩個分區,選取小的那個做 build input ,就是動態角色互換,這個動態角色互換發生在除第一對分區以外的分區上面。



Hash Join 算法

第 1 步:判定小表是否能夠全部存放在 hash area 內存中,如果可以,則做內存 hash join 。如果不行,轉第二步。

第 2 步:決定 fan-out 數。

(Number of Partitions) * C<= Favm *M

其中 C 為 Cluster size ,

?

其值為 DB_BLOCK_SIZE*HASH_MULTIBLOCK_IO_COUNT ; Favm 為 hash area 內存可以使用的百分比,一般為 0.8 左右; M 為 Hash_area_size 的大小。

第 3 步:讀取部分小表 S ,采用內部 hash 函數 ( 這里稱為 hash_fun_1) ,將連接鍵值映射至某個分區,同時采用 hash_fun_2 函數對連接鍵值產生另外一個 hash 值,這個 hash 值用于創建 hash table 用,并且與連接鍵值存放在一起。

第 4 步:對 build input 建立位圖向量。

第 5 步:如果內存中沒有空間了,則將分區寫至磁盤上。

第 6 步:讀取小表 S 的剩余部分,重復第三步,直至小表 S 全部讀完。

第 7 步:將分區按大小排序,選取幾個分區建立 hash table( 這里選取分區的原則是使選取的數據最多 ) 。

第 8 步:根據前面用 hash_fun_2 函數計算好的 hash 值,建立 hash table 。

第 9 步:讀取表 B ,采用位圖向量進行位圖向量過濾。

第 10 步:對通過過濾的數據采用 hash_fun_1 函數將數據映射到相應的分區中去,并計算 hash_fun_2 的 hash 值。

第 11 步:如果所落的分區在內存中,則將前面通過 hash_fun_2 函數計算所得的 hash 值與內存中已存在的 hash table 做連接, 將結果寫致磁盤上。 如果所落的分區不在內存中,則將相應的值與表 S 相應的分區放在一起。

第 12 步:繼續讀取表 B ,重復第 9 步,直至表 B 讀取完畢。

第 13 步:讀取相應的 (Si,Bi) 做 hash 連接。在這里會發生動態角色互換。

第 14 步:如果分區過后,最小的分區也比內存大,則發生 nested- loop hash join 。


Hash Join 的成本

1. 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)

?

2. On-Disk Hash Join

根據上述的步驟描述,我們可以看出

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 需要循環的次數。 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 參數的值并不一定提高 hash join 的性能。

當連接的兩個表是用等值連接并且表的數據量比較大時,優化器才可能采用哈希連接。哈希連接是基于CBO的。只有在數據庫

初始化參數HASH_JOIN_ENABLED設為True,并且為參數PGA_AGGREGATE_TARGET設置了一個足夠大的值的時候,Oracle才會使用哈

希邊連接。HASH_AREA_SIZE是向下兼容的參數,但在Oracle9i之前的版本中應當使用HASH_AREA_SIZE。當使用ORDERED提示時,

FROM子句中的第一張表將用于建立哈希表。

當缺少有用的索引時,哈希連接比嵌套循環連接更加有效。哈希連接也可能比嵌套循環連接更快,因為處理內存中的哈希表

比檢索B_樹索引更加迅速。 Hash Join 適合于小表與大表連接、返回大型結果集的連接。

深入地理解和掌握oracle的表連接對于優化數據庫的性能至關重要。由于優化器選擇方式的不同,以及統計信息的缺失或統

計信息的不準確,ORACLE自動選擇的表連接方式不一定是最優的。當SQL語句的執行效率很低時,可通過auto trace對執行計

劃進行跟蹤和分析。當出現多表連接時,需要仔細分析是否有更佳的連接條件。根據系統的特點,必要時可以在SQL中添加

HINTS,從而改變SQL的執行計劃,從而達到性能優化的目的。

6 索引連接

如果一組已存在的索引包含了查詢所需要的所有信息,那么優化器將在索引中有選擇地生成一組哈希表。可通過范圍或者快

速全局掃描訪問到每一個索引,而選擇何種掃描方式取決于WHERE子句中的可有條件。在一張表有大量的列,而您只想訪問有

限的列時,這種方法非常有效。WHERE子句約束條件越多,執行速度越快。因為優化器在評估執行查詢的優化路徑時,將把約

束條件作為選項看待。您必須在合適的列(那些滿足整個查詢的列)上建立索引,這樣可以確保優化器將索引連接作為可選

項之一。這個任務通常牽涉到在沒有索引,或者以前沒有建立聯合索引的列上增加索引。相對于快速全局掃描,連接索引的

優勢在于:快速全局掃描只有一個單一索引滿足整個查詢;索引連接可以有多個索引滿足整個查詢。

------end------


(url: http://www.linuxidc.com/Linux/2010-08/28282.htm)


與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的Oracle表连接深入浅出的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。