2012-08-09 61 views
0

我已經編寫了一個將文本值轉換爲日期/時間的標量函數(DYNAMIC_DATE)。例如,DYANMIC_DATE('T-1')(T-1 =今天減1 ='昨天')返回08-AUG-2012 00:00:00。它也接受日期字符串:DYNAMIC_DATE('10/10/1974')WHERE子句中的Oracle標量函數導致性能較差

該函數利用CASE語句解析唯一參數並計算相對於sysdate的日期。

雖然它並沒有使用在其模式中的任何表,它利用TABLE類型的存儲日期格式字符串:

TYPE VARCHAR_TABLE IS TABLE OF VARCHAR2(10); 
formats VARCHAR_TABLE := VARCHAR_TABLE ('mm/dd/rrrr','mm-dd-rrrr','rrrr/mm/dd','rrrr-mm-dd'); 

當我使用SELECT子句中的功能,在<1秒查詢返回:

SELECT DYNAMIC_DATE('MB-1') START_DATE, DYNAMIC_DATE('ME-1') END_DATE 
FROM DUAL 

如果我用它對付我們的約會維度表(共91311條記錄),查詢完成了<1秒:

SELECT count(1) 
from date_dimension 
where calendar_dt between DYNAMIC_DATE('MB-1') and DYNAMIC_DATE('ME-1') 

其他人,但是,如果它是用來對付一個更大的表正與功能問題(26301317個記錄):

/* 
cost: 148,840 
records: 151,885 
time: ~20 minutes 
*/ 
SELECT count(1) 
FROM ORDERS ord 
WHERE trunc(ord.ordering_date) between DYNAMIC_DATE('mb-1') and DYNAMIC_DATE('me-1') 

然而,相同的查詢,使用「硬編碼」日期,退貨相當迅速:

/* 
cost: 144,257 
records: 151,885 
time: 62 seconds 
*/ 
SELECT count(1) 
FROM ORDERS ord 
WHERE trunc(ord.ordering_date) between to_date('01-JUL-2012','dd-mon-yyyy') AND to_date('31-JUL-2012','dd-mon-yyyy') 

供應商的香草安裝不包括在ORDERING_DATE領域的指標。

的解釋這兩個查詢計劃是相似的:

與功能: using function

通過硬編碼日期: hard-coded dates

  • 是在DYNAMIC_DATE功能被在WHERE一再呼籲條款?
  • 還有什麼可以解釋這種差距?

** **編輯

NONUNIQUE索引加入到訂單表。兩個查詢都在1秒內執行<。兩種方案都是一樣的(方法),但具有該功能的方案成本較低。

我從功能中刪除了DETERMINISTIC關鍵字;查詢在1秒內​​執行<。

  • 問題是真的與函數還是與表相關?
  • 從現在開始的3年,這張表甚至更大時,如果我不包含關鍵字DETERMINISTIC,查詢性能會受損嗎?
  • DETERMINISTIC關鍵字對函數結果有任何影響嗎?如果我明天運行DYNAMIC_DATE('T-1'),我是否會得到與今天運行時相同的結果(08/09/2012)?如果是這樣,這種方法將無法工作。
+0

如果解釋計劃是相似的,這是否意味着它們不相同?如果它們不相同,你可以發佈這兩個計劃嗎? – 2012-08-09 15:09:09

+0

計劃是完全相同的(意思是步驟);只有總成本不同。 – craig 2012-08-09 15:16:16

+0

「ORDERS」中有多少條記錄? – Ollie 2012-08-09 15:17:54

回答

1

如果計劃的步驟是相同的​​,那麼完成的工作量應該是相同的。如果您追蹤會話(如SQL * Plus中的set autotrace on或類似事件10046跟蹤的更復雜的東西),或者如果您在DBA_HIST_SQLSTAT(假設您已獲得AWR表的許可訪問權)中查看,您是否看到(大致)相同的數量兩個查詢的邏輯I/O和CPU消耗是多少?運行第二個查詢時,您看到的運行時差異是否可能是數據緩存的結果?

+0

在我的測試中,我通常使用硬編碼後的函數執行查詢。這不會消除緩存的好處嗎? – craig 2012-08-09 15:35:05

+0

@craig - 你能查詢AWR表嗎?如果是這樣,'DBA_HIST_SQLSTAT'顯示查詢之間的時間差異在哪裏?由於PL/SQL經過的時間有差別嗎?你的函數是否被聲明爲「DETERMINISTIC」? – 2012-08-09 15:39:32

+0

它沒有被聲明爲'DETERMINISTIC'。這到底意味着什麼?我可以訪問'DBA_HIST_SQLSTAT'表。你能推薦一個查詢嗎? – craig 2012-08-09 15:45:09

1

我猜測問題不在於你的功能。嘗試在trunc(ord.ordering_date)上創建基於功能的索引並查看解釋計劃。

CREATE INDEX ord_date_index ON ord(trunc(ord.ordering_date)); 
+0

如果它有所作爲,我已經嘗試了沒有TRUNC()邏輯的兩個查詢。結果(即性能)是相似的。這會改變你的想法嗎? – craig 2012-08-09 15:37:12

+1

然後我想看看'DYNAMIC_DATE'函數,看看裏面發生了什麼。 – Annjawn 2012-08-09 15:46:36