四種聯結方法——《Oracle SQL 高階程式設計》筆記1
聯接的方法有四種:巢狀迴圈聯接、雜湊聯接、排序-合併聯接和笛卡爾連線
每個聯接方法都有兩個分支。所訪問的第一章表稱為驅動表(the driving table),訪問的第二張表則稱為內層表或被驅動表(inner 或 driven-to table)。最佳化器透過使用統計資訊和 where 子句中的篩選條件計算每個表分別返回多少行資料來確定那張表是驅動表,預估大小最小(塊、資料行、位元組)的表通常被作為驅動表。
巢狀迴圈聯接
巢狀迴圈聯接使用一次訪問運算所得到的結果集中的每一行來與另一個表進行對碰。如果結果集的大小是有限的,並且在用來聯接的列上建有索引的話,這種聯接的效率通常是最高的。巢狀迴圈聯結運算成本主要是讀取外層表中每一行並將其所匹配的內層表中的行聯結所需的成本。
這種聯接的強大之處在於所使用的記憶體是非常少的。因為資料行集一次只加工一行,所需開支也是非常小的。巢狀迴圈聯接的基本度量就是為了準備最終結果集所需要訪問的資料塊數目。
例:
select empno, ename, loc
from emp, dept
where emp.deptno = dept.deptno;
這個查詢處理過程如下虛擬碼:
for each row in (select empno, ename, deptno from emp) loop
for (select dname, loc from dept where deptno = outer.deptno) loop
if match then pass the row on to the next step
if inner join and no match then discard the row
if outer join and no match set inner column values to null and pass the row on to the next step
end loop;
end loop;
排序-合併聯接
排序-合併聯接獨立地讀取需要聯接的兩張表,對每張表中滿足 where 子句的資料行按照聯結鍵進行排序,然後對排序後的資料行集進行合併。對這種聯接方法來說,排序的開銷是最大的,但是一旦資料行集排序完成了,合併的過程是非常快的。為了進行合併,資料庫輪流操作兩個列表,比較最上面的資料行,丟棄在排序佇列中比另一列表中的最上面一行出現的早的資料行,並只返回匹配的行。
例:
select empno, ename, loc
from emp, dept
where emp.deptno = dept.deptno;
這個查詢處理過程如下虛擬碼:
select empno, ename, deptno from emp order by deptno
select dname, loc, deptno from dept order by deptno
compare the rowsets and return rows where deptno in both lists match
for an outer join, compare the rowsets and return all rows from the first list
setting column values for the other table to null
排序-合併聯接一般最適合於資料篩選條件有限並返回有限資料行的查詢。如果沒有可用的更直接訪問資料的索引時,排序-合併聯接也通常是較好的選擇。總而言之,在條件為非等式的時候排序-合併聯接通常是最好的選擇。如果資料行源非常大,排序-合併聯接就可能是唯一可行的選擇。
雜湊聯接(hash join)
雜湊聯接首先應用 where 子句中的篩選標準來獨立地讀取要進行聯結的兩個表。基於表和索引的統計資訊,被確定為返回最少行數的包被完全雜湊化到記憶體中。這個雜湊化了的表包含了原表的所有資料行並被基於將聯結鍵轉化為雜湊值的隨機行數載入到雜湊桶中。只要有足夠的記憶體空間,這個雜湊表將一直放在記憶體中,然而如果沒有足夠的記憶體,雜湊表將會被寫入到臨時磁碟空間。
下一步就是讀取另一個較大的表,並對聯結鍵列應用雜湊函式。然後利用這個雜湊值對較小的在記憶體中的雜湊表進行探測以尋找匹配的第一個表的行資料所在的雜湊桶。每個雜湊桶都有一個放在其中的資料雜湊表(透過點陣圖來表示)。這個列表被用來與探測行進行匹配。如果匹配成功則返回一行資料,否則丟棄。較大的表只讀取一次,並檢查其中的每一行來尋找匹配。這與巢狀迴圈聯結的不同之處在於此處內層表被多次讀取。因此事實上在這個例子中,較大的表是驅動表,因此僅讀取一次,而較小的雜湊表則被探測很多次。與巢狀迴路聯結執行計劃不同,在執行計劃的輸出中較小的雜湊表放在前面而較大的探測表放在後面。
例:
select empno, ename, loc
from emp, dept
where emp.deptno = dept.deptno;
這個查詢處理過程如下虛擬碼:
determine the smaller row set, or in the case of an outer join, use the outer joined table
select dname, loc, deptno from dept
hash the deptno column and build a hash table
select empno, ename, deptno from emp
hash the deptno column and probe the hash table
if match made, check bitmap to confirm row match
if no match made, discard the row
決定哪個表是最小的不僅取決於資料行數,還取決於這些行的大小,因為整個行都必須要存放在雜湊表中。當資料行源較大並且結果集也比較大的情況下,將更傾向於考慮雜湊聯接。或者,如果要聯結的其中一張表確定總是返回同一資料行源,也很可能會選用雜湊聯結,因為這樣僅訪問一次這張表。最後,如果較小的表可以放到記憶體中,雜湊聯結也會很受歡迎。
雜湊聯結僅在相等聯結的情況下才能進行。
笛卡爾聯結
笛卡爾聯結髮生在當一張表中的所有行與另一張表中的所有行聯結的時候。因此,這種聯接所得到的結果集總是=rows table A * rows table B。通常當連線條件被忽略或忽視以致沒有指定的聯結列,所能做的唯一可能的運算就是將一張表中的所有內容與另一張表中的所有內容聯結起來的時候會進行笛卡爾聯結。
例:
select empno, ename, loc
from emp, dept;
這個查詢處理過程如下虛擬碼:
determine the table
select dname, loc, deptno from dept
select empno, ename, deptno from emp
for each row in dept match it to every row in emp retaining all rows
每個聯接方法都有兩個分支。所訪問的第一章表稱為驅動表(the driving table),訪問的第二張表則稱為內層表或被驅動表(inner 或 driven-to table)。最佳化器透過使用統計資訊和 where 子句中的篩選條件計算每個表分別返回多少行資料來確定那張表是驅動表,預估大小最小(塊、資料行、位元組)的表通常被作為驅動表。
巢狀迴圈聯接
巢狀迴圈聯接使用一次訪問運算所得到的結果集中的每一行來與另一個表進行對碰。如果結果集的大小是有限的,並且在用來聯接的列上建有索引的話,這種聯接的效率通常是最高的。巢狀迴圈聯結運算成本主要是讀取外層表中每一行並將其所匹配的內層表中的行聯結所需的成本。
這種聯接的強大之處在於所使用的記憶體是非常少的。因為資料行集一次只加工一行,所需開支也是非常小的。巢狀迴圈聯接的基本度量就是為了準備最終結果集所需要訪問的資料塊數目。
例:
select empno, ename, loc
from emp, dept
where emp.deptno = dept.deptno;
這個查詢處理過程如下虛擬碼:
for each row in (select empno, ename, deptno from emp) loop
for (select dname, loc from dept where deptno = outer.deptno) loop
if match then pass the row on to the next step
if inner join and no match then discard the row
if outer join and no match set inner column values to null and pass the row on to the next step
end loop;
end loop;
排序-合併聯接
排序-合併聯接獨立地讀取需要聯接的兩張表,對每張表中滿足 where 子句的資料行按照聯結鍵進行排序,然後對排序後的資料行集進行合併。對這種聯接方法來說,排序的開銷是最大的,但是一旦資料行集排序完成了,合併的過程是非常快的。為了進行合併,資料庫輪流操作兩個列表,比較最上面的資料行,丟棄在排序佇列中比另一列表中的最上面一行出現的早的資料行,並只返回匹配的行。
例:
select empno, ename, loc
from emp, dept
where emp.deptno = dept.deptno;
這個查詢處理過程如下虛擬碼:
select empno, ename, deptno from emp order by deptno
select dname, loc, deptno from dept order by deptno
compare the rowsets and return rows where deptno in both lists match
for an outer join, compare the rowsets and return all rows from the first list
setting column values for the other table to null
排序-合併聯接一般最適合於資料篩選條件有限並返回有限資料行的查詢。如果沒有可用的更直接訪問資料的索引時,排序-合併聯接也通常是較好的選擇。總而言之,在條件為非等式的時候排序-合併聯接通常是最好的選擇。如果資料行源非常大,排序-合併聯接就可能是唯一可行的選擇。
雜湊聯接(hash join)
雜湊聯接首先應用 where 子句中的篩選標準來獨立地讀取要進行聯結的兩個表。基於表和索引的統計資訊,被確定為返回最少行數的包被完全雜湊化到記憶體中。這個雜湊化了的表包含了原表的所有資料行並被基於將聯結鍵轉化為雜湊值的隨機行數載入到雜湊桶中。只要有足夠的記憶體空間,這個雜湊表將一直放在記憶體中,然而如果沒有足夠的記憶體,雜湊表將會被寫入到臨時磁碟空間。
下一步就是讀取另一個較大的表,並對聯結鍵列應用雜湊函式。然後利用這個雜湊值對較小的在記憶體中的雜湊表進行探測以尋找匹配的第一個表的行資料所在的雜湊桶。每個雜湊桶都有一個放在其中的資料雜湊表(透過點陣圖來表示)。這個列表被用來與探測行進行匹配。如果匹配成功則返回一行資料,否則丟棄。較大的表只讀取一次,並檢查其中的每一行來尋找匹配。這與巢狀迴圈聯結的不同之處在於此處內層表被多次讀取。因此事實上在這個例子中,較大的表是驅動表,因此僅讀取一次,而較小的雜湊表則被探測很多次。與巢狀迴路聯結執行計劃不同,在執行計劃的輸出中較小的雜湊表放在前面而較大的探測表放在後面。
例:
select empno, ename, loc
from emp, dept
where emp.deptno = dept.deptno;
這個查詢處理過程如下虛擬碼:
determine the smaller row set, or in the case of an outer join, use the outer joined table
select dname, loc, deptno from dept
hash the deptno column and build a hash table
select empno, ename, deptno from emp
hash the deptno column and probe the hash table
if match made, check bitmap to confirm row match
if no match made, discard the row
決定哪個表是最小的不僅取決於資料行數,還取決於這些行的大小,因為整個行都必須要存放在雜湊表中。當資料行源較大並且結果集也比較大的情況下,將更傾向於考慮雜湊聯接。或者,如果要聯結的其中一張表確定總是返回同一資料行源,也很可能會選用雜湊聯結,因為這樣僅訪問一次這張表。最後,如果較小的表可以放到記憶體中,雜湊聯結也會很受歡迎。
雜湊聯結僅在相等聯結的情況下才能進行。
笛卡爾聯結
笛卡爾聯結髮生在當一張表中的所有行與另一張表中的所有行聯結的時候。因此,這種聯接所得到的結果集總是=rows table A * rows table B。通常當連線條件被忽略或忽視以致沒有指定的聯結列,所能做的唯一可能的運算就是將一張表中的所有內容與另一張表中的所有內容聯結起來的時候會進行笛卡爾聯結。
例:
select empno, ename, loc
from emp, dept;
這個查詢處理過程如下虛擬碼:
determine the table
select dname, loc, deptno from dept
select empno, ename, deptno from emp
for each row in dept match it to every row in emp retaining all rows
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30496894/viewspace-1806085/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- JavaScript高階程式設計筆記JavaScript程式設計筆記
- 《JavaScript高階程式設計》筆記:DOM(十)JavaScript程式設計筆記
- Javascript高階程式設計 學習筆記JavaScript程式設計筆記
- 《JavaScript 高階程式設計》精讀筆記JavaScript程式設計筆記
- oracle學習筆記(十七) PL/SQL高階應用Oracle筆記SQL
- python高階程式設計讀書筆記(一)Python程式設計筆記
- C#高階程式設計 讀書筆記C#程式設計筆記
- JavaScript 高階程式設計 第三章 讀書筆記(1)JavaScript程式設計筆記
- Java高階程式設計筆記 • 【第4章 網路程式設計】Java程式設計筆記
- node.js高階程式設計閱讀筆記Node.js程式設計筆記
- JavaScript高階程式設計筆記 - 第四章 變數 作用域 記憶體問題JavaScript程式設計筆記變數記憶體
- 高階shell程式設計筆記(第三十三章 雜項)程式設計筆記
- Unix高階程式設計學習筆記--系統呼叫簡介程式設計筆記
- 《javascript高階程式設計》學習筆記 | 7.3.生成器JavaScript程式設計筆記
- oracle學習筆記(十一) 高階查詢Oracle筆記
- JS高階程式設計第十三章.個人學習筆記JS程式設計筆記
- JS高階程式設計第十一章.個人學習筆記JS程式設計筆記
- JS高階程式設計第十六章.個人學習筆記JS程式設計筆記
- 《javascript高階程式設計》學習筆記 | 21.2.錯誤處理JavaScript程式設計筆記
- 《javascript高階程式設計》學習筆記 | 11.3.非同步函式JavaScript程式設計筆記非同步函式
- spark學習筆記--進階程式設計Spark筆記程式設計
- Rust 程式設計影片教程(進階)——026_1 高階 trait1Rust程式設計AI
- 四. 文字程式設計--Windows程式設計課程學習筆記程式設計Windows筆記
- 穀粒商城高階篇筆記1筆記
- Rust 程式設計影片教程(進階)——027_1 高階特性Rust程式設計
- Oracle 常用SQL筆記OracleSQL筆記
- 《JavaScript 高階程式設計》 讀書筆記--從原型鏈複習繼承JavaScript程式設計筆記原型繼承
- Rust 程式設計視訊教程(進階)——026_1 高階 trait1Rust程式設計AI
- Rust 程式設計視訊教程(進階)——027_1 高階特性Rust程式設計
- JavaScript DOM程式設計藝術筆記1JavaScript程式設計筆記
- 高階語言程式設計作業第四次程式設計
- 第四次高階程式語言設計作業
- 高階語言程式設計第四次作業程式設計
- 【讀書筆記】JavaScript高階程式設計(第3版)(第5-7章)筆記JavaScript程式設計
- 《UNIX環境高階程式設計》(APUE) 筆記第十一章 - 執行緒程式設計筆記執行緒
- Oracle高階培訓 第5課 學習筆記Oracle筆記
- Oracle高階培訓 第6課 學習筆記Oracle筆記
- Oracle高階培訓 第7課 學習筆記Oracle筆記
- Python 高階程式設計:深入探索高階程式碼實踐Python程式設計