2016-02-16 59 views
1

這裏是我的查詢,甲骨文HASH_JOIN_RIGHT_SEMI性能

SELECT si.* FROM 
FROM SHIPMENT_ITEMS si 
WHERE ID IN (SELECT ID FROM id_map WHERE code = 'A') 
    AND LAST_UPDATED BETWEEN TO_DATE('20150102','YYYYMMDD') - 1 AND TO_DATE('20150103','YYYYMMDD') 

SHIPMENT_ITEMS是一個非常大的表(10.1TB),id_map是一個非常小桌子(12行3列)。此查詢通過HASH_JOIN_RIGHT_SEMI並花費很長時間.SHIPMENT_ITEMS在ID列上分區。

如果我刪除與硬編碼值的子查詢,它執行好多了

SELECT si.* FROM 
    FROM SHIPMENT_ITEMS si 
    WHERE ID IN (1,2,3) 
     AND LAST_UPDATED BETWEEN TO_DATE('20150102','YYYYMMDD') - 1 AND TO_DATE('20150103','YYYYMMDD') 

,因爲它導致硬編碼我無法刪除子查詢。

鑑於id_map是一個非常小的表,我希望這兩個查詢執行非常相似。爲什麼第一個花費更長的時間。

我實際上試圖理解爲什麼這樣表現如此糟糕。

我預計動態分區修剪發生在這裏,我不能拿出爲什麼它沒有發生

https://docs.oracle.com/cd/E11882_01/server.112/e25523/part_avail.htm#BABHDCJG

+1

IN是對性能非常低你有沒有嘗試加入餐桌?或使用存在? – sagi

+0

這將有助於爲兩個查詢添加解釋計劃,以查看它們之間的區別。運行'解釋計劃select ...;'然後'select * from table(dbms_xplan.display);'然後在這裏發佈* entire *輸出。另外,這些真正的查詢正在運行?看起來他們會返回數百萬行,這通常沒有意義。你是比較返回所有行還是僅返回某些IDE的前N行的時間? –

回答

1

嘗試暗示no_unnest的理由。

SELECT si.* FROM 
FROM SHIPMENT_ITEMS si 
WHERE ID IN (SELECT /*+ NO_UNNEST */ ID FROM id_map WHERE code = 'A') 
    AND LAST_UPDATED BETWEEN TO_DATE('20150102','YYYYMMDD') - 1 AND TO_DATE('20150103','YYYYMMDD') 

CBO不會嘗試加入子查詢和使用它像過濾器

+1

你也可以向OP和其他人解釋這個提示的確切含義。 – sagi

+0

提示意味着CBO不會嘗試加入子查詢並像過濾器一樣使用它 – SkyWalker

+0

對我來說,對於閱讀它的人來說..提示:編輯你的問題並在那裏寫 – sagi

-1

而是「在」操作,使用存在使用和檢查查詢性能

SELECT si.* FROM 
FROM SHIPMENT_ITEMS si 
WHERE Exists (SELECT 1 FROM id_map map WHERE map.code = 'A' and map.ID = so.ID) 
    AND LAST_UPDATED BETWEEN TO_DATE('20150102','YYYYMMDD') - 1 AND TO_DATE('20150103','YYYYMMDD')