2014-04-04 35 views
1

我想優化查詢,我在where子句中使用函數()調用。函數調用pl/sql查詢優化where條款

function()只是改變日期的時區。

當我調用該函數作爲SELECT的一部分,它的執行速度極快(< 0.09秒對許多幾十萬行的表)

select 
    id, 
    fn_change_timezone (date_time, 'UTC', 'US/Central') AS tz_date_time, 
    value 
from a_table_view 
where id = 'keyvalue' 
and date_time = to_date('01-10-2014','mm-dd-yyyy') 

但是,此版本運行「永遠」 [指我許許多多分鐘]後停止

select id, date_time, value 
from a_table_view 
where id = 'keyvalue' 
and fn_change_timezone (date_time, 'UTC', 'US/Central') = to_date('01-10-2014','mm-dd-yyyy') 

(我知道我不得不更改日期進行比較,它只是舉例)

所以我的q題目了有兩方面:

  1. 如果該功能是如此之快的where子句之外,爲什麼這麼慢得多使用TRUNC()或其他功能(顯然TRUNC()沒有做一個表查找比說像我的功能 - 但仍然功能是非常非常快速的where子句)

  2. 在where子句之外完成此操作的替代方法是什麼?

我想這作爲一種替代,這似乎沒有任何好轉,但仍跑,直到我停止了查詢:

select 
    tz.date_time, 
    v.id, 
    v.value 
from 
    (select 
    fn_change_timezone(to_date('01/10/2014-00:00:00', 'mm/dd/yyyy-hh24:mi:ss'), 'UTC',  'US/Central') as date_time 
    from dual 
    ) tz 
    inner join 
(
    select 
    id, 
    fn_change_timezone (date_time, 'UTC', 'US/Central') AS v_date_time, 
    value 
    from a_table_view 
    where id = 'keyvalue' 
) v ON 
    v.tz_date_time = tz.date_time 

希望我解釋好這個問題。

+0

將函數創建爲「不變」或「常量」函數嗎?這告訴優化器它不需要爲每組相同的參數重新調用函數。 –

+0

我不明白這些與Oracle功能有關的術語。 Google搜索時沒有幫助。 – bbaley

+1

對不起,我的錯誤是,你想看看「確定性函數」。 http://www.dba-oracle.com/plsql/t_plsql_deterministic.htm –

回答

0

WHERE子句中的函數調用是一件壞事。問題是可能會爲表中的每一行調用該函數,這可能比選擇的集合多得多。這可能是一個真正的性能殺手(不要問我怎麼知道:-)。在SELECT列表中的函數調用的第一個版本中,只有在選擇了某行並將其添加到結果集時纔會調用該函數 - 在第二個版本中,可能會爲表中的每一行調用該函數。另外,根據你使用的Oracle版本,從SQL調用用戶函數可能會有很大的開銷,但是我認爲這種懲罰在10g以後的版本中已經基本消除。

好運。

分享和享受。

0

沒有與WHERE子句中使用函數至少有四個潛在問題:

  1. 功能可能會阻止索引。基於函數的索引可以解決此問題。
  2. 函數可能會阻止分區修剪。硬編碼值或者虛擬列分區是可能的解決方案,儘管在這種情況下這兩種解決方案都不會有幫助。
  3. 函數可能運行緩慢。即使該函數便宜,在SQL和PL/SQL之間切換通常也非常昂貴。一些可能的解決方案是DETERMINISTIC,PARALLEL_ENABLE,函數結果緩存,定義純SQL中的邏輯,或用12c定義SQL中的函數。
  4. 函數可能會導致不良基數估計。優化器難以猜測正常條件的結果,添加過程代碼使其更加困難。使用ASSOCIATE STATISTICS可以向優化器提供關於函數的成本和基數的一些信息。

沒有更多的信息,如解釋計劃,很難知道這個查詢的具體問題是什麼。

+0

可以理解,where子句中的函數調用是不好的,我不易優化。這就是爲什麼我正在尋找替代品。不幸的是,我不能將函數改爲確定性的,所以我很可能需要找到另一種方法來消除函數調用。 – bbaley

+0

如果沒有解釋計劃,很難判斷哪個選項有幫助。你甚至可能不需要改變函數,也許只是改變Oracle調用函數的方式(間接通過選項#4)。 –