2014-01-29 30 views
3

我們的表格「Customers」包含email和siteId列。還有一個由這兩列組成的索引。爲什麼索引不用於某些值?

select * from customers where email = '[email protected]'; 

我們可以保證指數使用,因爲我們已經檢查與解釋計劃查詢:那麼,通過電子郵件進行查詢時,並過濾,這樣一個相關的查詢總是用這個指標。現在,我們昨天有一個有趣的案例。有一個條目「email ='[email protected]'的查詢根本沒有使用索引,解釋計劃顯示oracle做了全面掃描,該表包含數百萬條記錄,所以這個沒有索引的查詢命中30秒。是查詢確實使用了任何其他電子郵件值([email protected][email protected])的索引。什麼原因爲什麼oracle沒有使用索引?

一個原因讓我想起索引不包含這樣的值,所以首先oracle遍歷索引,然後進行全面掃描,然後解釋計劃應該顯示它執行了索引掃描。在我們的案例中,解釋計劃只顯示全面掃描,另一個原因是它與db恢復有某種關係,但是,也不知道如何可以指數不包含這樣的價值。

UPDATE恢復後的所有表,都有last_analyzed一週齡的日期值。在電子郵件的這種特殊情況下,由於更新後的客戶隱私,所有電子郵件都會更新爲一些隨機值。客戶表有幾百萬條記錄,所以是的,恢復後有一個相當大的變化,但仍不明白它如何與不使用電子郵件有關,因爲這個客戶表在恢復之前已經有數百萬條記錄。

UPDATE2該索引在我們對錶執行收集統計後使用。

UDATE3好吧,所有的電子郵件值在客戶表中都是唯一的,所以CBO不太可能決定使用這種特定電子郵件的行數太多。只是有很多電子郵件的起始字符是「隨機的」,但不應該被認爲是相同的值,對吧?

+0

做的表包含頻繁的插入和刪除? – arunb2w

+2

如果沒有找到索引命中,則不會執行完整掃描;它會做一個或另一個,而不是兩個。 (它是否執行完整索引掃描或全表掃描?)假設您的統計數據是最新的,索引是否具有直方圖,並且您是否有許多類似於具有不同行爲的地址? –

+0

我的確同意Alex的說法,這可能是因爲特定電子郵件ID的基數很高的原因,因此Oracle會進行全表掃描。 – San

回答

2

服務器不會查看索引中的數據,然後在未找到的情況下掃描表。在執行任何操作之前,它會查看統計信息以查看它是否應使用索引或掃描表。我猜想通過電子郵件地址,出於某種原因,甲骨文認爲掃描表比查看索引更好。有太多的因素需要得出確切的結論。查看統計信息Oracle Doc on Stats。您可能會考慮更改索引統計信息的數據量,這將有所幫助。

+2

從描述開始,我將從[查看直方圖]開始(http://docs.oracle.com/cd/B13789_01/server.101/b10752/stats.htm #40819)作爲該決定的理由。 –

+0

@AlexPoole有趣的東西,謝謝。另請參閱更新的問題。 – Centurion

0

直方圖僅考慮第一個 32個字節。相同的起始字符有多大?詳情請參閱this Oracle Optimizer post

移動唯一的字符的字符串或禁用直方圖的開頭是這樣的:

begin 
    dbms_stats.set_table_prefs 
    (
    '<schema>', 
    'CUSTOMERS', 
    'METHOD_OPT', 
    'FOR ALL COLUMNS SIZE AUTO, FOR COLUMNS SIZE 1 EMAIL' 
); 
end; 
/
+0

有趣的一點,但在我們的情況下,以「random」開頭的郵件只包含6個相同的字節(隨機),所以直方圖也應該考慮其他字符。 – Centurion

相關問題