Oracle 表連線的方法 (下)

2021-07-31 10:18:10 字數 3822 閱讀 6110

雜湊連線

雜湊連線僅適用於cbo

oracle 10g 以後的版本: 隱含引數_hash_join_enabled

use_hash hint的引數優先順序高於_hash_join_enabled

oracle中兩個表t1和t2 做雜湊連線,那麼步驟如下:

1:首先oracle會根據引數hash_area_size 和 db_block_size 和hash_multblock_io_count 來決定hash partition 的數量。(hash partition是乙個邏輯上概念,包括一組hash bucket ,乙個hash table又是hash partiton的集合)

2兩個表按照目前sql中的謂詞進行過濾,得到的結果集較少的那個表,作為驅動結果集。

假設t1對應的結果集為s t2對應的結果集為b,設s為驅動結果集,b設為被驅動結果集。

3oracle遍歷s,讀取s中的每一條記錄,並對每一條記錄按照s1中的連線列,使用oracle內建的hash函式,計算hash值。oracle中有兩個內建的雜湊函式,分別記為hash_func_1 hash_func_2 ,所對應的結果記為hash_vlaue_1 hash_vlaue_2

4oracle 按照hash_value_1 把相應的s中的記錄儲存在不同的hash partition的不同的hash bucket中去。同時和記錄存放在一起還有hash_vaule_2 。儲存在hash bucket裡的記錄並不是目標表的完整行記錄,只需要儲存位於目標sql中與目標表相關的查詢列和連線列。把s中對應的每乙個hash partition 記為si。

5在構建si的同時,oracle會構建乙個位圖,這個位圖用來標記si所包含的每乙個hash bucket是否有記錄。

6 如果s的數量巨大,那可能存在把pga的工作區 worke area 被填滿的情況。這時oracle會把工作區中包含記錄數最多的hash partition 寫到磁碟上,接著oracle會繼續構建s所對應的hash table。如果繼續出現被填滿的情況,那麼就重複上述步驟。 直至結果集s被遍歷完成。

7oracle會對si進行排序,目的是將記錄數較小的hash partition 寫在記憶體中,記錄數大的寫到磁碟上。

8現在oracle開始遍歷b,讀取b中每一條記錄,並按照該記錄在表t2中的連線列做雜湊運算,此步驟上面和上面一樣。 oracle會按照該記錄對應的hash_value_1 去si裡找相匹配的hash bucket,如果能找到匹配的hash bucket ,則開始遍歷hash bucket中每一條記錄,幷校檢儲存於該hash bucket記錄中每乙個連線列,是否真的匹配。如果匹配,則返回相應的結果。如果找不到匹配的,則會訪問步驟5中的點陣圖。

如果點陣圖的記錄顯示該hash bucket在si中對應的記錄數大於0 ,則說明此hansh bucket不在記憶體中,但是在磁碟中。此時oracle就會按照hash value_1 把值相應的b中的記錄以hash partition的方式寫回到磁碟,同時存放的還有hash_value_2 。如果點陣圖中顯示記錄數為0,則表示沒有對應的記錄。 這個過程被稱為 「位圖過濾」。

相應把b所對應的每乙個hash partition 記為bj

9查詢hash bucket 和構建bj的過程會一直持續下去,直到遍歷完成b中的所有記錄。

10記憶體中的記錄已經匹配完成,現在需要匹配磁碟上的si和bj。

11因為構建si和bj時,使用的是同樣的雜湊函式,所以oracle在處理位於磁碟上的si和bj的時候,可以放心的配對處理。即只有對應hash partition number值相同的si和bj才可能產生滿足連線條件的記錄。這裡我們sn和bn來表示位於磁碟上且對應hash partition number值相同的si和bj。

12對於每一對sn和bn,它們之中記錄數較少的會被當作驅動結果集,oracle會用這個驅動結果集hash bucket裡記錄的hash_value_2來構建新的hash table,另外乙個記錄數較多的當作被驅動結果集,然後oracle會用這個被驅動結果集hash bucket裡的記錄hash_value_2 去上述構建的hash table中找匹配記錄。 對於與每一對sn和bn而言,oracle始終會選擇他們中記錄數較少的作為被驅動結果集,所以每一對sn和bn的被驅動結果集都可能發生變化,這就是所謂的動態角色互換。

13上述步驟中,如果匹配的相應記錄,則返回結果。

14處理完成所有的sn和bn後,此過程結束。

雜湊連線的優缺點如下:

1 雜湊連線不需要排序

2 雜湊連線的驅動表對應的連線的可選擇性應盡可能的好,這個會影響hash bucket的數量。而hash bucket 記錄數又會直接影響從該hash bucket 中查詢匹配記錄的效率。

3 雜湊連線只適用於cbo,只能用於等值連線

4 雜湊連線很適合小表和大表之間做表連線,且連線結果集的記錄數較多的情形。

5 當兩個表做雜湊連線時,如果在施加了目標sql中指定的謂詞條件,後得到的資料較小的結果集,所構建的hash table可以容納在pga的工作區,則此時雜湊鏈結的效率會很高。

ps: 驅動結果集和被驅動結果,在巢狀迴圈連線和雜湊連線中都存在,而且都是記錄數較少的作為驅動結果集,但是原因不同:

巢狀迴圈連線中,第一層迴圈的數量是確定的,並且等於驅動結果集的記錄數,(可以說是全表掃瞄)而第 二層查詢時,可以按照索引的方式來完成。如果被驅動結果集的索引的可選擇性良好的情況下,影響巢狀迴圈效率的原因就是第一層的全表掃瞄,因此全表掃瞄越少越好。

雜湊連線中,驅動結果集的所有資料需要構建hash table,如果資料較大,那麼占用的快取和硬碟空間必然增多,尤其當過多的資料正好填滿pga的 work area時。被驅動結果集理論上只需要查詢和匹配,並不一定要構建hash table,所以資料過多無妨。

笛卡爾連線:

兩個表t1 t2做笛卡爾連線的步驟如下

1: 對於t1施加目標sql中的謂詞條件,得到結果集1

2 對t2施加目標sql中的謂詞條件,得到結果集2

3 遍歷1 中的每一條記錄,和2中的每一條記錄相匹配,得到最後的結果。

反連線:

是一種特殊型別的連線,與內連線和外連線都不同。

含義如下: t1.x.anti = t2.y來表示t1和t2進行反連線。反連線條件為 t1.x=t2.y。那麼t1.x.anti = t2.y表示,只要在表t2中有滿足條件t1.x=t2.y的記錄存在,則t1中滿足條件t1.x=t2.y的記錄就會被刪除,最後返回t1那些不滿足條件的記錄。

在子查詢時,oracle經常會把not exists ,not in, <>all換成對應的反連線。

not in 和<>all  對null敏感,即如果not in後面的子查詢結果集中存在null,那麼最終就會返回null,即不包含任何記錄,

not exists 對null不敏感。

半連線

半連線的意思就是只要在表t2中找到滿足條件的值,就立刻返回。半連線和普通的內連線不同,半連線會去重。

oracle中的exists ,in, =any會轉為對應的半連線。

oracle表的連線

表連線操作有內連線和外連線兩種 1 內連線 也稱等值連線或自然連線,內連線是從結果表中刪除與其他被連線表中沒有匹配行的所有元組,所以當匹配條件不滿足時內連線可能會丟失資訊。例如 select from emp e,dept d where e.deptno d.deptno 2 外連線 外連線分為三...

Oracle表連線方式

實用記憶方法 在哪邊,哪邊就是外來鍵,該錶的資料就 少 無 那邊檢索的就是全表資料。oracle 8i,9i 表連線方法。一般的相等連線 select from a,b where a.id b.id 這個就屬於內連線。對於外連線 oracle中可以使用 來表示,9i可以使用left right f...

oracle表連線(二)

各類連線驅動順序區別 1.巢狀迴圈連線 select leading t1 use nl t2 from t1,t2 where t1.id t2.t1 id and t1.n 19 select leading t2 use nl t1 from t1,t2 where t1.id t2.t1 i...