2016-06-29 153 views
0

我在使用具有聚合函數的SQL查詢時遇到了一些性能問題,所以我認爲理解索引創建如何正確工作是個好主意。我遇到一件事我不明白就來了:是這兩位創作指令?:Oracle索引創建語法

1.)CREATE INDEX FIELD1_INDEX ON TABLE1 (FIELD1) ONLINE TABLESPACE XXX; 
    CREATE INDEX timeofrequest_INDEX ON TABLE1 (timeofrequest) ONLINE TABLESPACE XXX; 

2.)CREATE INDEX COMBINED_INDEX ON TABLE1 (FIELD1, FIELD2) ONLINE TABLESPACE XXX; 

的原因,我問的區別是,我有一個像查詢:

SELECT SUM(field1) FROM table1 WHERE timeofrequest BETWEEN 1 AND 2; 

Table1包含大量數據,因此該查詢需要20秒以上才能做好準備。爲了避免很長的運行時間,我嘗試使用方法1,併爲每個受影響的字段創建一個索引。事實上,它仍然太慢。從分析執行計劃中,我看到使用timeofrequest索引,但不使用field1。如果我創建一個帶有單個語句的組合語句,它應該有幫助嗎?它有什麼區別?

回答

0

因此,您的前兩個索引與第三個索引不同,因爲前兩個索引只使用一個SINGLE列。您的第三個索引由您的索引的兩個不同列組成,但第三個索引仍可以使用,即使您只提供索引中列出的第一列......這被稱爲組合索引。 Oracle實際上只能在單個查詢語句中使用SINGLE索引,並且CBO將找出最佳選擇。

在第一個示例中,您針對各個列有兩個索引。你的第二個例子是有兩列的SINGLE索引。你的第一個例子將只使用一個或另一個,但不能同時用於任何給定的單個select語句(CBO將根據你的查詢決定使用什麼...)。

例子:

SELECT SUM(field1) FROM table1 WHERE timeofrequest BETWEEN 1 AND 2; 

這隻會嘗試使用你已經把對timeofrequest索引。實際上它會嘗試進行範圍掃描。

例爲第二個索引:

SELECT SUM(field1) FROM table1 WHERE FIELD1 = 'x'; 

假設你沒有一個INDEX只針對「FIELD1」,這會利用你在地方有COMBINED_INDEX,每索引的第一個字段獲取所有記錄。

如果您有:

SELECT SUM(field1) FROM table1 WHERE FIELD2 = 'y'; 

這不會使用combined_index,因爲該指數是建立在首先使用FIELD1,FIELD2然後。

如果您有:

SELECT SUM(field1) FROM table1 WHERE FIELD1 = 'x' and FIELD2 = 'y'; 

這仍然會利用COMBINED_INDEX,但在這裏你提供更細的粒度級別。它會利用完整的索引(field1和field2 ...)以更快的速度返回你的行。爲什麼這很有用?那麼,你可能在FIELD1上有一個索引,只需要在ONLY field1上搜索,仍然會產生數千(或數萬,或數百萬)記錄,所以能夠提供另一列作爲索引的一部分將簡單地幫助您定位您需要的記錄......這反過來提供了更高的選擇性。

重要提示!請記住,CBO會找出最佳方法。如果你的基數很差(研究表基數...)在你的表上,根據CBO,甚至可能根本就不使用索引,並且全表掃描會更好。如果您的基數很高,但仍未使用索引,則可能需要分析表格及其索引,然後重新運行解釋計劃以查看是否獲得新結果。由於表中的很多數據都在變化,並且最近沒有對其進行分析,所以也可能由於基數太大而導致基數較低。分析你的表格/索引是一件非常重要的事情,很容易被忽視。在多次場合,我發現我工作的實例只是重新分析表格和/或索引而做出了令人難以置信的改進。

請檢查分析表和使用DBMS_STATS。

https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_stats.htm

另一種解決方案也就是如果你有大量的數據,而你的「的要求時間」列實際上只有一小組不同的值(也許在你的50萬條記錄表中有隻20個不同的值..),那麼你可以選擇設置一個分區表,並從那裏提供索引。這將極大地提高查詢性能。

+0

非常感謝,感謝您的幫助 –