Oracle索引詳解(二)
--索引分類
Oracle 提供了大量索引選項。知道在給定條件下使用哪個選項對於一個程序的性能來說非常重要。一個錯誤的選擇可能會引發死鎖,並導致數據庫性能急劇下降或進程終止。而如果做出正確的選擇,則可以合理使用資源,使那些已經運行了幾個小時甚至幾天的進程在幾分鍾得以完成,極大的提高數據操作語句的運行效率。
導讀【2017-12-26】【22:35:36】:
-
- B 樹索引(默認類型)
- 位圖索引
- HASH 索引
- 索引組織表索引
- 反轉鍵(reverse key)索引
- 基於函數的索引
- 分區索引(本地和全局索引)
- 位圖連接索引
- B 樹索引(默認類型)
一、B 樹索引
B 樹索引在 Oracle 中是一個通用索引。在創建索引時它就是默認的索引類型。B 樹索 引可以是一個列的(簡單)索引,也可以是組合/復合(多個列)的索引。B 樹索引最多可以包括 32 列。 索引列的值都存儲在索引中。因此,可以建立一個組合(復合)索引,這些索引可以直 接滿足查詢,而不用訪問表。這就不用從表中檢索數據,從而減少了 I/O 量。
特點:
- 適合與大量的增、刪、改(OLTP);
- 不能用包含 OR 操作符的查詢;
- 適合高基數的列(唯一值多);
- 典型的樹狀結構;
- 每個結點都是數據塊; 大多都是物理上一層、兩層或三層不定,邏輯上三層;
- 葉子塊數據是排序的,從左向右遞增;
- 在分支塊和根塊中放的是索引的范圍;
二、位圖索引
位圖索引非常適合於決策支持系統(Decision Support System,DSS)和數據倉庫,它們不應該用於通過事務處理應用程序訪問的表。它們可以使用較少到中等 基數(不同值的數量)的列訪問非常大的表。盡管位圖索引最多可達 30 個列,但通常它們都只用於少量的列。對於有較低基數的列需要使用位圖索引,比如性別。 在一個查詢中合並多個位圖索引后,可以使性能顯著提高。位圖索引 使用固定長度的數據類型要比可變長度的數據類型好。較大尺寸的塊也會提高對 位圖索引的存儲和讀取性能。
特點:
- 適合與決策支持系統;
- 做 UPDATE 代價非常高;
- 非常適合 OR 操作符的查詢;
- 基數比較少的時候才能建位圖索引;
三、HASH 索引
使用 HASH 索引必須要使用 HASH 集群。建立一個集群或 HASH 集群的同 時,也就定義了一個集群鍵。這個鍵告訴 Oracle 如何在集群上存儲表。在存儲數據時,所有與這個集群鍵相關的行都被存儲在一個數據庫塊上。 HASH 索引在有限制條件(需要指定一個確定的值而不是一個值范圍)的情況下非常有用。
特點:
- HASH 索引可能是訪問數據庫中數據的最快方法,但它也有自身的缺點,低估了集群鍵的不同值的數字可能會造成集群的沖突 ;
- 如果不能為集群的未來增長分配好附加的空間,HASH 集群可能就不 是最好的選擇;
- 如果應用程序經常在集群表上進行全表掃描,HASH 集群可能也 不是最好的選擇;
- 通常,HASH 對於一些包含 有序值的靜態數據非常有效;
四、索引組織表
索引組織表會把表的存儲結構改成 B 樹結構,以表的主鍵進行排序。這種特殊的表和其他類型的表一樣,可以在表上執行所有的 DML 和 DDL 語句。由於表的特殊結構,ROWID 並沒有被關聯到表的行上。
對於一些涉及精確匹配和范圍搜索的語句,索引組織表提供了一種基於鍵的快速數據訪問機制。基於主鍵值的 UPDATE 和 DELETE 語句的性能也同樣得以提高,這是因為行在物理上有序。由於鍵列的值在表和索引中都沒有重復,存儲所需要的空間也隨之減少。
如果不會頻繁地根據主鍵列查詢數據,則需要在索引組織表中的其他列上創建二級索引。不會頻繁根據主鍵查詢表的應用程序不會了解到使用索引組織表的全部優點。對於總是通過對主鍵的精確匹配或范圍掃描進行訪問的表,就需要考慮使用索引組織表,可以在索引組織表上建立二級索引
五、反轉鍵索引
當載入一些有序數據時,索引肯定會碰到與 I/O 相關的一些瓶頸。在數據載 入期間,某部分索引和磁盤肯定會比其他部分使用頻繁得多。為了解決這個問題, 可以把索引表空間存放在能夠把文件物理分割在多個磁盤上的磁盤體系結構上。
為了解決這個問題,Oracle 還提供了一種反轉鍵索引的方法。如果數據以反轉鍵索引存儲,這些數據的值就會與原先存儲的數值相反。這樣,數據 1234、1235 和 1236 就被存儲成 4321、5321 和 6321。結果就是索引會為每次新插入 的行更新不同的索引塊。
技巧:
- 如果您的磁盤容量有限,同時還要執行大量的有序載入,就可以使用反轉鍵索引。
- 不可以將反轉鍵索引與位圖索引或索引組織表結合使用。因為不能對位圖索引和索引組織表進行反轉鍵處理。
六、基於函數的索引
可以在表中創建基於函數的索引。如果沒有基於函數的索引,任何在列上執行了函數的查詢都不能使用這個列的索引。例如,下面的查詢就不能使用 JOB 列上的索引,除非它是基於函數的索引:
1 select * from emp where UPPER(job) = 'MGR';
下面的查詢使用 JOB 列上的索引,但是它將不會返回 JOB 列具有 Mgr 或 mgr 值的行:
1 select * from emp where job = 'MGR';
可以創建這樣的索引,允許索引訪問支持基於函數的列或數據。可以對列表 達式 UPPER(job)創建索引,而不是直接在 JOB 列上建立索引,如:
1 create index EMP$UPPER_JOB on emp(UPPER(job));
盡管基於函數的索引非常有用,但在建立它們之前必須先考慮下面一些問題:
- 能限制在這個列上使用的函數嗎?如果能,能限制所有在這個列上執行的所有函數嗎?
- 是否有足夠應付額外索引的存儲空間?
- 在每列上增加的索引數量會對針對該表執行的 DML 語句的性能帶來何種影響?
基於函數的索引非常有用,但在實現時必須小心。在表上創建的索引越多,INSERT、UPDATE 和 DELETE 語句的執行就會花費越多的時間。 注意:對於優化器所使用的基於函數的索引來說,必須把初始參數 QUERY_REWRITE _ ENABLED 設定為 TRUE。
示例:
1 select count(*) from sample where ratio(balance,limit) >.5; 2 time: 20.1 minutes 3 4 create index ratio_idx1 on sample (ratio(balance, limit)); 5 6 select count(*) from sample where ratio(balance,limit) >.5; 7 time: 7 seconds