表連接執行有三種方式,分別爲:嵌套循環Nested Loop Joins,哈希連接 Hash Joins,排序合併Sort Merge Joins
對於嵌套循環連接執行的方式:兩表謂詞過濾後的數據用雙層循環的形式進行比較,選擇出符合關聯條件的行,外層循環爲驅動表,內層循環爲被驅動表,外層循環每有一條記錄,就需要內層循環查找一次。
優化條件:1.兩表連接列上建立索引
2.選擇合適的驅動表(絕大部分情況小表做驅動表,此處一般爲優化器自己選擇)
選擇小表爲驅動表的原理:
兩表連接每次的where條件關聯只返回一條記錄,存在2張表,一個10條記錄,一個1000萬條記錄,若2表都存在連接字段索引
小表爲驅動表的代價:10*(通過索引在大表查詢一條記錄的代價),大概10*5
大表爲驅動表的代價:1000萬*(通過索引在小表查詢一條記錄的代價),大概1000萬*3
通過索引獲取一條記錄(取一條記錄那在表裏肯定就是一個塊了,除非那行大於塊的大小8k),10行的表代價通常在3 blocks,索引2塊,表1塊。1000萬的表代價通常5 blocks,索引可能達到4塊,表1塊
hash連接的執行方式:也有驅動表,被驅動表的概念,選擇驅動表所有符合條件的數據執行hash算法映射到內存,然後依次選擇被驅動表的數據執行相同hash算法,看是否與內存中的數據匹配,僅限等值連接。
優化:1.驅動表要小,要能全部放在內存中
排序合併連接的方式: 合併排序,顧名思義,就是通過將兩個有序的序列合併爲一個大的有序的序列的方式來實現排序。合併排序是一種典型的分治算法:首先將序列分爲兩部分,然後對每一部分進行循環遞歸的排序,然後逐個將結果進行合併。
假如有A、B兩張表進行排序合併連接,ORACLE會首先將A表進行排序,形成一張臨時的“表”C,然後將B進行排序,形成一張臨時的“表”D,然後將C與D進行合併操作,返回結果集。就是兩個行源分別按照關聯字段排序以後,做關聯。
優化: 1.連接列建立索引
2.要有足夠內存 (合併排序最大的優點是它的時間複雜度爲O(nlgn),這個是我們之前的選擇排序和插入排序所達不到的。他還是一種穩定性排序,也就是相等的元素在序列中的相對位置在排序前後不會發生變化。他的唯一缺點是,需要利用額外的N的空間來進行排序。)
借鑑別人的總結:
訪問次數|嵌套循環|驅動表返回幾條,被驅動表訪問多少次
|——————————————————————————————————————
|哈希連接|表都最多訪問一次
|--------------------------------------------------------------------------
|排序合併|表都最多訪問一次
---------------------------------------------------------------------------
適應場景|嵌套循環|小量數據的連接或小表大表連接
|——————————————————————————————————————
|哈希連接|大數據的連接或小表大表連接
|--------------------------------------------------------------------------
|排序合併|大數據的連接且有排序操作
---------------------------------------------------------------------------
排序差異|嵌套循環|無排序
|-------------------------------------------------------------
|哈希連接|無排序,但會消耗內存建立Hash表
|--------------------------------------------------------------
|排序合併|有排序
----------------------------------------------------------------
限制場景|嵌套循環|無任何限制,<>,>,<,like都可以用
| ——————————————————————————
|哈希連接|只能使用=
| -----------------------------------------------------
|排序合併|無任何限制,<>,>,<,like都可以用
----------------------------------------------------
索引使用|嵌套循環|驅動表的限制條件和被驅動表的連接條件上創建索引
| ------------------------------------------------------------
|哈希連接|索引列無要求,與單表情況無異
| -----------------------------------------------------------
|排序合併|索引可以消除排序
---------------------------------------------------------
需要注意連接時,要避免笛卡爾積,即避免字段應該是多對多的關係,即連接鍵儘量不能有重複值。
感謝以下文章作者,借鑑其中部分內容:
http://blog.itpub.net/30126024/viewspace-2127136/