2009-09-18 153 views
21

您是否需要按照Oracle數據庫中的字段爲組的字段創建索引?爲分組字段創建索引?

例如:

select * 
from some_table 
where field_one is not null and field_two = ? 
group by field_three, field_four, field_five 

我測試我的上述和該查詢的唯一相關的索引創建的索引爲field_two創建的索引。其他任何字段上創建的其他單字段或複合索引都不會用於上述查詢。這聽起來正確嗎?

回答

11

這可能是正確的,但這取決於你有多少數據。通常,我會爲我在GROUP BY中使用的列創建索引,但在您的情況下,優化程序可能已決定在使用field_two索引後沒有足夠的數據返回來證明使用GROUP的其他索引通過。

+1

+1提到優化器,這可能是最可能的原因。 – 2009-09-18 14:59:14

+0

謝謝你的迴應。我沒有意識到解釋計劃取決於表中的數據量。表中目前沒有數據,這就解釋了優化器可能跳過其他索引的原因。 在另一個說明中,只有field_three和field_four沒有field_five的複合索引仍然會用在像上面那樣的查詢中嗎?這不包括group by子句中的所有字段。 – onejigtwojig 2009-09-18 15:04:01

+0

@Mark - 解釋它。請參閱我的編輯,以獲取有關Oracle可以使用哪些索引的更多信息。 – 2009-09-18 15:08:29

7

不,這可能是不正確的。

如果您有一個大表,Oracle可能更喜歡從索引而不是表中導出字段,即使沒有涵蓋所有值的單個索引。

在我的博客最新文章:

,存在一種Oracle不使用全表掃描,而是將兩個指標來獲取列值的查詢:

SELECT l.id, l.value 
FROM t_left l 
WHERE NOT EXISTS 
     (
     SELECT value 
     FROM t_right r 
     WHERE r.value = l.value 
     ) 

的計劃是:

SELECT STATEMENT 
HASH JOIN ANTI 
    VIEW , 20090917_anti.index$_join$_001 
    HASH JOIN 
    INDEX FAST FULL SCAN, 20090917_anti.PK_LEFT_ID 
    INDEX FAST FULL SCAN, 20090917_anti.IX_LEFT_VALUE 
    INDEX FAST FULL SCAN, 20090917_anti.IX_RIGHT_VALUE 

正如您所見,t_left這裏沒有TABLE SCAN

相反,Oracle呈現idvalue指標,加入他們的rowid並得到從加入結果(id, value)雙。

現在,您的查詢:

SELECT * 
FROM some_table 
WHERE field_one is not null and field_two = ? 
GROUP BY 
     field_three, field_four, field_five 

首先,它不會編譯,因爲你是從表一中GROUP BY條款選擇*

您需要用基於非分組列的分組列和聚合的表達式替換*

您將最有可能從以下索引中獲益:

CREATE INDEX ix_sometable_23451 ON some_table (field_two, field_three, field_four, field_five, field_one) 

,因爲它將包含在field_two一切兩個過濾,排序上field_three, field_four, field_five(爲GROUP BY有用),並確保field_oneNOT NULL

+1

非常有趣 - 我不認爲我以前見過(Oracle會加入兩個索引並完全避免表) – 2009-09-18 15:09:51

+0

'@Eric Petroelje':有一個特殊的提示'INDEX_JOIN',強制這個方法。 – Quassnoi 2009-09-18 15:19:23

2

您是否需要在Oracle數據庫中按字段創建組字段的索引?

不需要,無論是否存在任何索引,查詢都會運行。提供索引來提高查詢性能。

但是,它可以幫助;但我不願意添加索引來幫助查詢,而不考慮新索引對數據庫的可能影響。

...此查詢的唯一相關索引是爲field_two創建的索引。其他任何字段上創建的其他單字段或複合索引都不會用於上述查詢。這聽起來正確嗎?

並不總是如此。通常GROUP BY將要求Oracle執行排序(但不總是);您可以通過在要排序的列上提供合適的索引來消除排序操作。

但是,您是否真的需要擔心GROUP BY的性能,這是您需要考慮的一個重要問題。

+0

upvote for「可以消除排序操作..」。順便說一句,這篇文章有更多的細節http://use-the-index-luke.com/sql/sorting-grouping/indexed-group-by – waltersu 2017-06-20 13:22:54