2016-03-03 47 views
0

在我的生產環境我有一個有意義的差異,當我在選擇直接調用的函數和函數Oracle的性能,當我「包裝」的選擇,然後調用然後函數外(下面我告訴你兩個簡單的例子)與在選擇

在第一種情況下(當直接調用函數時),結果查詢在35秒內結束。

在第二種情況下(函數包裝),結果在7秒內結束。

當然,查詢是exatcly相同,結果行也是一樣的。

在兩種方式中調用同一個函數是有區別的嗎?

慢版:

select col1, col2, myFun(col3) 
    from aTable; 

快速版本

select col1, col2, myFun(col3) 
    from (select col1, col2, col3 
      from aTable); 
+0

你確定那纔是真正的查詢?沒有'WHERE'或'JOIN'或類似的東西? – Thilo

+0

@ Mistre83:你有沒有試過在兩個陳述上做一個'EXPLAIN'? –

+0

函數到底是什麼?高管的計劃是什麼?函數執行多少次? – ibre5041

回答

2

假設有100萬行的aTable,但你真正的查詢有一個返回只有10行的WHERE子句:

select col1, col2, myFun(col3) 
    from aTable 
    join ... 
    join ... 
where ...; 

Oracle 可能決定在加入和過濾之前調用函數myFun,因此它將被稱爲100萬次。由於上下文切換,從SQL調用PL/SQL函數的速度很慢。

當你把它包像這樣:

select col1, col2, myFun(col3) 
    from (select col1, col2, col3 
      from aTable 
      join ... 
      join ... 
      where ... 
     ); 

...現在甲骨文可能要進行聯接和過濾第一,獲得10行回來,然後調用myFun 10倍。

如果每個函數調用需要0.001秒,那麼這將花費百萬* 0.001 = 1,000秒鐘的第一查詢,和10 * 0.001 = 0.01秒的第二包裹查詢。

請注意,我說的可能可能 - 優化器可以做出不同的選擇,這取決於統計數據 - 因此對於某些查詢這兩個版本可以調用該函數只有10倍,或兩者稱之爲100萬次。

此提示應確保第二個版本總是很快,告訴甲骨文沒有這兩個查詢合併爲一個:

select /*+ no_merge(v) */ col1, col2, myFun(col3) 
    from (select col1, col2, col3 
      from aTable 
      join ... 
      join ... 
      where ... 
     ) v; 
+0

我也應該這樣做...也許在第一個版本的功能是適用於每一行,在第二個版本的功能是應用結果(用join/where表示)的行較少。謝謝! – Mistre83