2011-11-16 66 views
1

我運行在指定的日期範圍相當大的查詢。查詢大約需要30秒,除非我做了10/01/2011-10/31/2011的範圍。由於某些原因,範圍永遠不會結束。例如01/01/2011-01/31/2011,以及幾乎所有其他範圍,都會在預期的時間內完成。甲骨文日期範圍Inconsistancy

而且,我發現,這樣做更小的範圍內,比如一週,花費的時間比大範圍長。

+2

你使用綁定變量還是使用硬編碼文字?你使用的是什麼版本的Oracle?日期欄中是否有柱狀圖?統計數據(包括直方圖)是否準確?你有不同的查詢計劃嗎?如果是這樣,那麼「好」計劃是什麼樣子?「壞」計劃是什麼樣子? –

+0

我們使用的是10g,我正在使用綁定變量。我很確定日期欄中沒有直方圖。我實際上是一名Java開發人員,我對直方圖並不熟悉。該列上有一個索引,正在使用它。當我更改日期時,查詢計劃完全不同。我從來沒有去檢查,因爲如果查詢是相同的,計劃將是相同的。不好的計劃使用了大量的嵌套循環,而好的計劃不使用。另外,糟糕的計劃正在使用我以前沒有見過的「查看推定謂詞」的操作。 – Dave

+2

查看列統計我注意到最後的分析是在2011年9月26日。通過強制更新分析,問題得到解決。我現在的問題是數據爲什麼陳舊,我可以告訴我們的DBA如何確保它們保持最新狀態? – Dave

回答

2

當甲骨文收集表上的統計信息,它會記錄低值和日期列高值並用它來估計謂詞的基數。如果您在列上創建直方圖,它將收集有關列內數據分佈的更詳細信息。否則,Oracle基於成本的優化器(CBO)將採用統一的分佈。

例如,如果您有一個包含100萬行的表格和一個DATE列,其值爲2001年1月1日的較低值,2011年1月1日的值較高,則它會假定大約10%的數據範圍爲2001年1月1日 - 2002年的數據,大約0.027%將來自一些時間在2008年(1 /(10年*每年+飛躍天365天)

3月3日,1月1日,

只要您的查詢使用日期從已知的範圍內,優化器的基數估計一般都非常好,所以它什麼打算使用的決定都還不錯。如果你去有點超出上限或下限,估計仍相當不錯,因爲優化器假定可能有更大或更小的數據它是在對數據進行採樣以收集統計數據時看到的。但是當你離優化器統計期望看到的範圍太遠時,優化器的基數估計會變得太離譜,並且最終會選擇一個不好的計劃。你的情況,以刷新統計之前,優化期待的最大值可能是9月25日或26日,2011年當您的查詢看起來爲2011年10月的月數據,優化最有可能預期該查詢將返回非常少的行,並選擇了針對該場景優化的計劃,而不是針對實際返回的大量行。鑑於返回的實際數據量,這使計劃變得更糟。

在Oracle 10.2中,當Oracle執行硬解析併爲加載到共享池的查詢生成計劃時,它會查看綁定變量值並使用這些值來估計查詢將返回的行數因此是最有效的查詢計劃。一旦創建了查詢計劃,並且直到計劃超出共享池時,相同查詢的後續執行將使用相同的查詢計劃,而不考慮綁定變量的值。當然,由於計劃已經過時,下次查詢必須進行嚴格分析時,Oracle會查看並且可能會看到新的綁定變量值。

Bind variable peeking不是特別深受喜愛的功能(自適應遊標共享在11g是更好),因爲它使一個DBA或開發人員能夠預測會在任何特定時刻使用什麼計劃很難因爲你永遠無法確定優化器在硬解析過程中看到的綁定變量值是否代表您通常看到的綁定變量值。例如,如果您正在搜索1天範圍內,索引掃描幾乎肯定會更有效。如果您搜索5年以上的範圍,表掃描幾乎肯定會更有效。但是你最終會在硬解析中使用任何計劃。

最有可能的是,您可以簡單地通過確保在基於單調遞增值範圍(日期列是最常見的這種列)頻繁查詢的表上收集更頻繁的統計信息來解決問題。就你而言,在問題出現之前已經收集了大約6周的統計數據,因此根據收集統計數據的成本如何,確保每個月或幾周收集統計數據可能是安全的。

您也可以使用DBMS_STATS.SET_COLUMN_STATS過程更爲經常地爲此列明確設置統計信息。這需要更多的編碼和工作,但爲您節省了收集統計數據的時間。這在數據倉庫環境中可能非常有用,但它可能在更正常的OLTP環境中過度使用。

+0

謝謝賈斯汀的詳細解釋。你讓我想要學習我的數據庫調優技巧。 – Dave