2017-02-21 39 views
0

我有一個大的Oracle表與索引DATE_TIME場:「DISCONNECT_DATE」如何使用Oracle索引字段的查詢

當我使用下面的where子句我的查詢運行速度快:

DISCONNECT_DATE > TO_DATE('01-DEC-2016', 'DD-MON-YYYY') AND 
DISCONNECT_DATE < TO_DATE('01-JAN-2017', 'DD-MON-YYYY') 

當我用下面的where子句我的查詢運行(很)緩緩道:

extract(month from disconnect_date) = '12' and 
extract(year from disconnect_date) = '2016' 

他們都或多或少相當於他們的意圖。爲什麼前者工作,後者不工作? (我不認爲我在SQL SERVER這個問題)

(我用的PL SQL Developer來編寫查詢)

+0

我猜Oracle無法自動將您的第二個選項轉換爲第一個選項,因此它會進行全面掃描。這需要一個特殊情況來進行優化。 PS。除非你改變> => = –

+0

我很困惑。你是說在SQL Server中這兩個版本運行速度非常快嗎?我對SQL Server一無所知,但我會覺得非常驚訝。 (除非你已經在SQL Server中有基於函數的索引,就像Gordon在答案中所展示的那樣)。 – mathguy

回答

4

的問題是使用索引。首先,所有功能都在「常量」一側,而不是「列」一側。因此,Oracle很容易看到可以應用索引。

雖然索引的邏輯不理解extract(),所以索引沒有被使用。如果你想使用結構,你可以在函數調用創建一個索引:

create index idx_t_ddyear_ddmonth on t(extract(month from disconnect_date), extract(year from disconnect_date)); 

注:extract()沒有返回一個數字的字符串,所以你應該擺脫單引號的。混合數據類型也會混淆優化器。

+0

你是什麼意思是「常量」與「列」之間的差異。您是否有過一個例子,其中一方或另一方對Oracle產生了影響?我一直認爲它沒有任何區別。 –

+0

@WW - 左側與右側不一樣;您可以交換條件,以便「列」引用位於操作符的右側(也可以更改操作符,以便在需要時保持邏輯相同)。這是指直接或通過操作(如函數調用,這是此處的問題)來自列的數據,與非基於列的表達式進行比較。無論哪一方都在。 [閱讀詳情](https://docs.oracle.com/database/121/SQLRF/sql_elements002.htm#SQLRF00214),注意第二個項目符號點以及關於管理隱式數據類型轉換的規則部分: –

+0

@WW - 請密切注意Gordon在最後一段中所說的內容(關於正確匹配表達式的數據類型)。他是100%正確的 - 我敢打賭,由於對數據類型的疏忽,因爲使用圍繞列值的函數(比如'extract()),所以更多的效率丟失了(全球所有查詢運行在全球所有數據庫上) '在你的例子中)。獎金++給戈登花時間表達這一點! – mathguy