2016-06-16 116 views
0

我有一個表,其中我跟蹤事件及其發生日期。 在某些情況下,事件發生的日期爲空(甚至是尚未發生,但已註冊)日期,空值和索引

快速統計:所有事件390K行,其與空日期252K的

所以拉,當我有問題基於用戶請求的數據: 1.用戶可能需要拉事件尚未發生; (用戶輸入*) 2.用戶可以提取超出特定日期的事件; 3.用戶可以拉出發生在特定日期之後的事件+尚未發生的事件;

我建立動態的SQL查詢,像

select 
    even_id, 
    event_registered_date, 
    event_name, 
    event_occurred_date 
from 
    events_table 
where 
    NVL(event_occurred_date, to_date('2033-01-01','yyyy-mm-dd')) >= coalesce(to_date(replace(:p1, '*', NULL),'yyyy-mm-dd'),event_occurred_date,to_date('2033-01-01','yyyy-mm-dd')) 
    ...--other filter conditions are here 

這個SQL中最耗費成本的部分是日期過濾器。我試圖創建基於函數的索引trunc(event_occurred_date),甚至包括空值trunc(NVL(event_occurred_date,to_date('2033-01-01','yyyy-mm-dd')))它仍然使用全表掃描。

我相信有更加微妙的解決方法,但我只是沒有看到它。 在此先感謝

補充: 我剛問過表的所有者,他們告訴我說,事件中至少有一半會在任何給定時間有event_occurred_date。也許這將有助於分析 執行計劃: 所有的execution plan

+0

爲什麼不使用默認值(例如2033-01-01,您使用NVL動態填充)設置空日期值?這似乎是解決大部分問題的好方法。 –

+0

另一種解決方案可以將查詢拆分爲兩部分 - 其中一個日期爲空的部分,其自然會較慢(因爲沒有明顯的過濾器並且它是大部分數據 - 因此索引不是選項),而另一個日期不爲空,它將使用索引來查詢日期特定的事件。 –

+0

不幸的是我不能影響表格填充的方式,所以我必須照原樣工作。關於分成兩行的 ,我只能使用一個sql查詢,而我提供的上一部分是我在較大選擇中使用的JOIN之一。所以這也無濟於事。感謝您的建議 – user2858200

回答

1

首先建立索引後 - 你分析的指標?

假設你有 - 你沒有提到你正在運行的查詢類型。 如果查詢參數正在搜索NULL - 我不會驚訝於優化器選擇使用索引範圍掃描的全表掃描。 因此,大部分記錄集都有一個空日期值。

您也可以使用提示來強制使用索引 即。/* + index(events_table_idx)*/

但是您需要仔細查看性能統計信息以確定哪種方式是檢索數據的最有效方式。

+0

在結果sql select中沒有'where event_occurred_date is NULL'部分,它應該符合一般模式:當用戶輸入'*'時應該是 - 然後我應該跳過檢查'event_occurred_date'(意思是,無論是否發生過日期,包括空值),當用戶輸入一個日期,那麼它應該檢查輸入的日期。 是的,我試着指定索引提示,它仍然使用全表掃描,我認爲這是比索引範圍掃描更快。 – user2858200