oracle錶鏈接的優化

多表鏈接的三種方式: HASH JOIN,MERGE JOIN,NESTED LOOPhtml

NESTED LOOP: 嵌套循環鏈接,適用於內表數據量較小時。外表返回的每一行都要在內表中檢索找到與它匹配的行,所以整個查詢返回的結果集不能太大(大於1 萬不適合),並且在內表的鏈接字段上最好創建索引。sql

HASH JOIN: 哈希/散列鏈接,適用於小表(驅動表)連大表,且較小的表徹底能夠放於內存中的狀況。可是在表很大的狀況下並不能徹底放入內存,這時優化器會將它分割成若干不一樣的分區,不能放入內存的部分就把該分區寫入磁盤的臨時段,此時要有較大的臨時段從而儘可能提升I/O 的性能。架構

SORT MERGE JOIN: 排序合併鏈接,適用於沒有索引且數據已經排序、不等價關聯等狀況一般狀況下散列鏈接的效果都比排序合併鏈接要好,然而若是行源已經被排過序,在執行排序合併鏈接時不須要再排序了,這時排序合併鏈接的性能會優於散列鏈接。oracle

1、 大表關聯的優化方法 -- hash分區app

參考連接:20億與20億表關聯優化方法(超級大表與超級大表join優化方法)函數

問題:兩個20億大表關聯耗時一天一晚上post

執行的SQL: select * from t1,t2 where t1.object_id=t2.object_id;性能

關聯慢的緣由:單個進程的PGA裝不下大表數據 --> 消耗大量臨時表空間 --> 臨時表來回讀寫優化

優化方法:url

1)開並行,並行hash。 -- 不可行

2)利用MPP架構/HADOOP架構思想:數據分割。

數據分割方法:一個是分區;另一個是分表。本文選用分區。

步驟:

1)建立表P1,P2。在T1的表結構基礎上多加一個字段HASH_VALUE,並且依據HASH_VALUE進行LIST分區。同理,P2。

注意:工做中具體須要多少分區需本身判斷,但P1和P2表的分區必須如出一轍。 

CREATE TABLE P1(
HASH_VALUE NUMBER,
OWNER VARCHAR2(30),
OBJECT_NAME VARCHAR2(128),
SUBOBJECT_NAME VARCHAR2(30), 
OBJECT_ID NUMBER,
DATA_OBJECT_ID NUMBER,
OBJECT_TYPE VARCHAR2(19),
CREATED DATE,
LAST_DDL_TIME DATE,
TIMESTAMP VARCHAR2(19),
STATUS VARCHAR2(7),
TEMPORARY VARCHAR2(1),
GENERATED VARCHAR2(1),
SECONDARY VARCHAR2(1),
NAMESPACE NUMBER,
EDITION_NAME VARCHAR2(30)
)   
   PARTITION BY  list(HASH_VALUE)
(
partition p0 values (0),
partition p1 values (1),
partition p2 values (2),
partition p3 values (3),
partition p4 values (4)
)

 2)向P1,P2中插入數據。

oracle中的hash分區就是利用的ora_hash函數。

partition by hash(object_id)  <=> ora_hash(object_id,4294967295)

ora_hash(列,hash桶) ,hash桶默認是4294967295,可以設置0到4294967295。

ora_hash(object_id,4) 會把object_id的值進行hash運算,而後放到 0,1,2,3,4 這些桶裏面。

delete t1 where object_id is null;
commit;

delete t2 where object_id is null;
commit;

insert into p1
select ora_hash(object_id,4), a.*  from t1 a;  ---工做中用append parallel並行插入
commit;

insert into p2
select ora_hash(object_id,4), a.*  from t2 a;  ---工做中用append parallel並行插入
commit;

3)執行表關聯。

優化後執行時間大約1小時。可將該過程整理爲存儲過程。

select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=0 and p2.hash_value=0;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=1 and p2.hash_value=1;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=2 and p2.hash_value=2;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=3 and p2.hash_value=3;
select * from p1,p2 where p1.object_id=p2.object_id and p1.hash_value=4 and p2.hash_value=4;

 

 2、小表與大表關聯 -- hash join

參考連接:oracle錶鏈接----->哈希鏈接(Hash Join)

對Hash Join的一次優化

1)執行hash join

select /*+ leading(t1) use_hash(t2)*/ * from t1,t2 where t1.id=t2.t1_id;  --可連個表都創建hash,  use_hash(t1 t2)

2)查看執行計劃

若是條件成立,驅動表和被驅動表都只被訪問1次(主要看 starts),不然訪問0次。

哈希鏈接中驅動表的選擇很是重要,性能(主要看 A-Time  | Buffers |  OMem |  1Mem | Used-Mem)差異也大。通常選用結果集較小的表(非數據量)爲驅動表

-- 查看執行代碼的 sql_id
select sql_id, child_number, sql_text from v$sql where sql_text like '%use_hash(t2)%';

-- 查看指定 sql_id 的執行計劃
select * from table(dbms_xplan.display_cursor('036fyatp73h9n',0,'allstats last'));

3)其餘

hash join 不支持不等值鏈接。(執行計劃走的是 NESTED LOOPS JOIN)

explain plan for select /*+ leading(t2) use_hash(t1)*/ * from t1,t2 where t1.id<>t2.t1_id and t1.num=20;

select * from table(dbms_xplan.display);

  

  參考連接:

https://zhidao.baidu.com/question/453003972.html

相關文章
相關標籤/搜索