在作表join的時候, Oracle有三種方式, 與其說有三種方式, 不如說是三種策略。 sql
分別是: oracle
根據個人理解來說講這三種策略。 oop
首先講講Row Source, 根據Oracle官方的解釋, 性能
Row source is a row set returned by a step in the execution plan along with a control structure that can iteratively process the rows. The row source can be a table, a view or result of a join or grouping operation. spa
總之, Row source是oracle根據執行計劃生成的可操做數據集, 這種說法比Table更爲嚴謹,由於join的兩側多是view或者其餘的object. code
1) sort merge join. 排序
例如: 索引
select * from t1 inner join t2 on t1.id=t2.id 內存
首先會把row source1(t1)先載入內存, 進行排序, 而後把row source2(t2)載入內存,進行排序,而後進行merge操做。 資源
什麼是merge 操做?就是將兩邊的行按照鏈接條件連起來, (t1.id=t2.id)。
不難看出,這種方式將須要鏈接的兩張表中的列都放到內存中,而後進行排序,而排序是一個消耗資源的操做,這樣對於兩張比較大的表,性能恐怕會比較差。
因此, 這種策略適合於表比較小, 或者在鏈接列上有索引的表。由於索引列已經排過序了。
2) Nested loops
選定一張表作爲驅動表,Oracle會遍歷驅動表中的每一行,根據鏈接條件去匹配第二張表中的行。
好比第一張表中有50行數據, 第二張表中有100行數據, 這樣遍歷的時間約等於50*100+50*磁頭切換時間
若是選擇第二張表做爲驅動表,遍歷時間約等於100*50+100*磁頭切換時間。
可見使用小表做爲驅動表能夠減小I/O,性能會比較好。
例如:
select from t1 inner join t2 on t1.id=t2.id
以上的這個hint 表明的是按照sql中指定的表順序進行鏈接。也就是我把t1做爲驅動表(Driving table).
Orace會根據t1中的每一行, 去尋找t2中知足t1.id=t2.id的行,而後返回到結果集。
不難看出, 若是在內部表的查詢列上有索引的話, 查詢的效率將提高。
聽說,對於可並行執行的大表, 使用分區了的大表做爲Driving table,性能會比較好,由於會在每一個分區上並行執行,可是取決於硬件是否支持多個磁盤,多個CPU並行執行,這個我並無試過,因此不敢妄加定論。
3) Hash Join
僅針對CBO有效。
使用較小的Row source 做爲Hash table和Bitmap. 而第二個row source被hashed,根據bitmap與第一個row source生成的hash table 相匹配,bitmap查找的速度極快。
例如:
select * from t1 inner join t2 on t1.id=t2.id
特別的,當Hash Table很大而不能所有留存在內存中的時候,這種Join策略更爲實用。
可是,因爲Bitmap自己的限制, 這種join策略只適用在等值鏈接的狀況下。
並且,在計算Hash Table的時候, 須要考慮系統Hash_Area_Size參數設置。
show parameter hash_area_size