論索引的重要性
1.以前雖然知道索引可以優化查詢速度。但是一直沒有怎麽重視。所以建表的時候也基本不會太多考慮索引的事。
2.至從遇到一張有50多萬條數據的表裏查數據
select m.miid from MemberInfo m where m.userid=301212
起先這個where 條件的userid字段 是沒有加索引的。執行時間11秒左右。
3.加上索引之後。該語句執行時間0.016秒,這速度的提升是相當可怕的。
這次的經歷讓我重新認識了索引的重要性。再次記錄
以下附數據庫查詢優化
-----------------------
索引是數據庫中一種可選的數據結構,她通常與表或簇相關。用戶可以在表的一列或數列上建立索引,以提高在此表上執行 SQL 語句的性能。就像本文檔的索引可以幫助讀者快速定位所需信息一樣,Oracle 的索引提供了更為迅速地訪問表數據的方式。正確地使用索引能夠顯著的減少磁盤 I/O。
用戶可以為一個表創建多個索引,只要不同索引使用的列或列的組合(combination of columns)不同即可。例如,下列語句中指定的列組合是有效的:
CREATE INDEX employees_idx1 ON employees (last_name, job_id);
CREATE INDEX employees_idx2 ON employees (job_id, last_name);
Oracle 提供了各種類型的索引,她們能夠互為補充地提升查詢性能:
- 平衡樹索引(B-tree index)
- 平衡樹簇索引(B-tree cluster index)
- 哈希簇索引(hash cluster index)
- 反向鍵索引(reverse key indexes)
- 位圖索引(bitmap index)
- 位圖連接索引(bitmap join index)
Oracle 還支持函數索引(function-based index),以及針對特定應用程序或程序模塊(cartridge)的域索引(domain index)。
無論索引是否存在都無需對已有的 SQL 語句進行修改。索引只是提供了一種快速訪問數據的路徑,因此她只會影響查詢的執行速度。當給出一個已經被索引的數據值後,就可以通過索引直接地定位到包含此值的所有數據行。
索引在邏輯上和物理上都與其基表(base table)是相互獨立的。用戶可以隨時創建(create)或移除(drop)一個索引,而不會影響其基表或基表上的其他索引。當用戶移除一個索引時,所有的應用程序仍然能夠繼續工作,但是數據訪問速度有可能會降低。作為一種獨立的數據結構,索引需要占用存儲空間。
當索引被創建後,對其的維護與使用都是 Oracle 自動完成的。當索引所依賴的數據發生插入,更新,刪除等操作時,Oracle 會自動地將這些數據變化反映到相關的索引中,無需用戶的額外操作。
即便索引的基表中插入新的數據,對被索引數據的查詢性能基本上能夠保持穩定不變。但是,如果在一個表上建立了過多的索引,將降低其插入,更新,及刪除的性能。因為 Oracle 必須同時修改與此表相關的索引信息。
優化器可以使用已有的索引來建立(build)新的索引。這將加快新索引的建立速度。
5.8.1 唯一索引和非唯一索引
索引(index)可以是唯一(unique)的或非唯一(nonunique)的。在一個表上建立唯一索引(unique index)能夠保證此表的索引列(一列或多列)不存在重復值。而非唯一索引(nonunique index)並不對索引列值進行這樣的限制。
Oracle 建議使用 CREATE UNIQUE INDEX 語句顯式地創建唯一索引(unique index)。通過主鍵(primary key)或唯一約束(unique constraint)來創建唯一索引不能保證創建新的索引,而且用這些方式創建的索引不能保證為唯一索引。
5.8.2 復合索引
復合索引(composite index)(也被稱為連結索引(concatenated index))是指創建在一個表的多列上的索引。復合索引內的列可以任意排列,她們在數據表中也無需相鄰。
如果一個 SELECT 語句的 WHERE 子句中引用了復合索引(composite index)的全部列(all of the column)或自首列開始且連續的部分列(leading portion of the column),將有助於提高此查詢的性能。因此,索引定義中列的順序是很重要的。大體上說,經常訪問的列(most commonly accessed)或選擇性較大的列(most selective)應該放在前面。
一個常規的(regular)復合索引(composite index)不能超過 32 列,而位圖索引(bitmap index)不能超過 30 列。索引中一個鍵值(key value)的總長度大致上不應超過一個數據塊(data block)總可用空間的一半。
5.8.3 索引和鍵
索引(index)與鍵(key)是連個不同的概念,但是這兩個術語經常被混用。索引是在數據庫中實際存儲的數據結構,用戶可以使用 SQL 語句對其進行創建(create),修改(alter),或移除(drop)。索引提供了一種快速訪問表數據的途徑。而鍵只是一個邏輯概念。鍵的概念主要在 Oracle 的完整性約束(integrity constraint)功能中使用,完整性約束用於保證數據庫中的業務規則(business rule)。
因為 Oracle 也會使用索引(index)來實現某些完整性約束(integrity constraint),因此索引與鍵(key)這兩個術語經常被混用。註意不要將二者混淆。
5.8.4 索引和空值
對於一個數據表的兩行或多行,如果其索引列(key column)中全部非空(non-NULL)的值完全相同(identical),那麽在索引中這些行將被認為是相同的;反之,在索引中這些行將被認為是不同的。因此使用 UNIQUE 索引可以避免將包含 NULL 的行視為相同的。以上討論並不包括索引列的列值(column value)全部為 NULL 的情況。
Oracle 不會將索引列(key column)全部為 NULL 的數據行加入到索引中。不過位圖索引(bitmap index)是個例外,簇鍵(cluster key)的列值(column value)全部為 NULL 時也是例外。
5.8.5 函數索引
如果一個函數(function)或表達式(expression)使用了一個表的一列或多列,則用戶可以依據這些函數或表達式為表建立索引,這樣的索引被稱為函數索引(Function-Based Index)。函數索引能夠計算出函數或表達式的值,並將其保存在索引中。用戶創建的函數索引既可以是平衡樹類型(B-tree index)的,也可以是位圖類型(bitmap index)的。
用於創建索引的函數可以是一個數學表達式(arithmetic expression),也可以是使用了 PL/SQL 函數(PL/SQL function),包函數(package function),C 外部調用(C callout),或 SQL 函數(SQL function)的表達式。用於創建索引的函數不能包含任何聚合函數(ggregate function),如果為用戶自定義函數,則在聲明中必須使用 DETERMINISTIC關鍵字。如果在一個使用對象類型(object type)的列上建立函數索引,則可以使用此對象的方法(method)作為函數,例如此對象的 map 方法。用戶不能在數據類型為 LOB,REF,或嵌套表(nested table)的列上建立函數索引,也不能在包含 LOB,REF,或嵌套表等數據類型的對象類型列上建立函數索引。
5.8.5.1 使用函數索引
如果一個 SQL 語句的 WHERE 子句中使用了函數,那麽建立相應的函數索引(function-based index)是提高數據訪問性能的有效機制。表達式(expression)的結果經過計算後將被存儲在索引中。但是當執行 INSERT 和 UPDATE 語句時,Oracle 需要進行函數運算以便維護索引。
例如,如果用戶創建了以下函數索引:
CREATE INDEX idx ON table_1 (a + b * (c – 1), a, b);
當 Oracle 處理如下查詢時就可以使用之前建立的索引:
SELECT a FROM table_1 WHERE a + b * (c – 1) < 100;
使用 UPPER(column_name) 或 LOWER(column_name) 函數建立函數索引(function-based index)有助於與大小寫無關(case-insensitive)的查詢。例如創建以下函數索引:
CREATE INDEX uppercase_idx ON employees (UPPER(first_name));
有助於提高以下查詢的性能:
SELECT * FROM employees WHERE UPPER(first_name) = ‘RICHARD’;
5.8.5.2 函數索引的優化
用戶必須為優化器(optimizer)收集關於函數索引(unction-based index)的統計信息(statistic)。否則處理 SQL 語句時將不會使用此索引。
當一個查詢的 WHERE 子句中含有表達式(expression)時,優化器可以對函數索引(function-based index)進行索引區間掃描(index range scan)。例如以下查詢:
SELECT * FROM t WHERE a + b < 10;
如果使用表達式(expression) a+b 建立的索引,優化器(optimizer)就能夠進行索引區間掃描(index range scan)。如果謂詞(predicate,即 WHERE 子句)產生的選擇性(selectivity)較低,則對區間掃描極為有利。此外,如果表達式的結果物化在函數索引內(function-based index),優化器將能更準確地估計使用此表達式的謂詞的選擇性。
優化器(optimizer)能夠將 SQL 語句及函數索引(function-based index)中的表達式解析為表達式樹(expression tree)並進行比較,從而實現表達式匹配。這個比較過程是大小寫無關的(case-insensitive),並將忽略所有空格(blank space)。
5.8.5.3 函數索引的依賴性
函數索引(function-based index)依賴於索引定義表達式中使用的函數。如果此函數為 PL/SQL 函數(PL/SQL function)或包函數(package function),當函數聲明(function specification)發生變化時,索引將失效(disabled)。
用戶需要被授予(grant)CREATE INDEX 或 CREATE ANY INDEX 權限才能創建函數索引(function-based index)。
要想使用函數索引(function-based index):
- 建立索引後,表必須經過分析(analyze)。
- 必須保證查詢的條件表達式不是 NULL 值, 因為 NULL 值不會被存儲到索引中。
以下各節將講述使用函數索引的其他需求。
5.8.5.3.1 DETERMINISTIC 函數
函數索引(function-based index)使用的用戶自定義函數(user-written function)必須聲明為 DETERMINISTIC,此關鍵字表明對於一定的輸入參數,此函數總會得到相同的輸出結果。
5.8.5.3.2 定義函數的權限
函數索引(function-based index)的所有者(owner)必須具備此索引定義中使用的函數的EXECUTE 權限。當 EXECUTE 權限被收回(revoke)後,Oracle 則將索引標識為 DISABLED。索引的所有者無須具備此函數的 EXECUTE WITH GRANT OPTION 權限,即可將索引所在表的SELECT 權限授予(grant)其他用戶。
5.8.5.3.3 解決函數索引的依賴性問題
函數索引(function-based index)依賴於她使用的所有函數。如果函數或函數所在包的聲明(specification)被修改過(或索引所有者對函數的 EXECUTE 權限被收回),將會出現以下情況:
- 索引被標記為 DISABLED。
- 如果優化器(optimizer)選擇了在標記為 DISABLED 的索引上執行查詢,那麽此查詢將失敗
- 使用標記為 DISABLED 的索引而執行的 DML 操作將失敗,除非此索引同時被標記為UNUSABLE 且初始化參數(initialization parameter) SKIP_UNUSABLE_INDEXES 被設為TRUE。
函數被修改之後,用戶可以使用 ALTER INDEX … ENABLE 語句將索引重新置為 ENABLE 狀態。
5.8.6 索引是如何存儲的
當用戶創建索引時,Oracle 會自動地在表空間(tablespace)中創建索引段(index segment)來存儲索引的數據。用戶可以通過以下方式控制索引段的空間分配和使用:
- 設置索引段的存儲參數(storage parameter)來控制如何為此索引段分配數據擴展(extent)
- 為索引段設置 PCTFREE 參數,來控制組成數據擴展的各個數據塊(data block)的可用空間情況。
索引段(index segment)使用的表空間(tablespace)既可以是索引所有者(owner)的默認表空間,也可以是在 CREATE INDEX 語句中指定的表空間。索引無需和其相關的表位於同一表空間中。相反,如果將索引與其相關表存儲在不同磁盤上能夠提升使用此索引的查詢性能,因為此時 Oracle 能夠並行地(parallel)訪問索引及表數據。
5.8.6.1 索引塊的格式
一個數據塊(data block)內可用於存儲索引數據的空間等於數據塊容量減去數據塊管理開銷(overhead),索引條目管理開銷(entry overhead),rowid,及記錄每個索引值長度的 1 字節(byte)。
當用戶創建索引時,Oracle 取得所有被索引列的數據並進行排序,之後將排序後索引值和與此值相對應的 rowid 按照從下到上的順序加載到索引中。例如,以下語句:
CREATE INDEX employees_last_name ON employees(last_name);
Oracle 先將 employees 表按 last_name 列排序,再將排序後的 列及相應的 rowid 按從下到上的順序加載到索引中。使用此索引時,Oracle 可以快速地搜索已排序的 last_name 值,並使用相應的 rowid 去定位包含用戶所查找的 last_name 值的數據行。
5.8.6.2 索引的內部結構
Oracle 使用平衡樹(B-tree)存儲索引以便提升數據訪問速度。當不使用索引時,用戶必須對數據進行順序掃描(sequential scan)來查找指定的值。如果有 n 行數據,那麽平均需要掃描的行為 n/2。因此當數據量增長時,這種方法的開銷將顯著增長。
如果將一個已排序的值列(list of the values)劃分為多個區間(range),每個區間的末尾包含指向下個區間的指針(pointer),而搜索樹(search tree)中則保存指向每個區間的指針。此時在 n 行數據中查詢一個值所需的時間為 log(n)。這就是 Oracle 索引的基本原理。
在一個平衡樹索引(B-tree index)中,最底層的索引塊(葉塊(leaf block))存儲了被索引的數據值,以及對應的 rowid。葉塊之間以雙向鏈表的形式相互連接。位於葉塊之上的索引塊被稱為分支塊(branch block),分枝塊中包含了指向下層索引塊的指針。如果被索引的列存儲的是字符數據(character data),那麽索引值為這些字符數據在當前數據庫字符集(database character set)中的二進制值(binary value)。
對於唯一索引(unique index),每個索引值對應著唯一的一個 rowid。對於非唯一索引(nonunique index),每個索引值對應著多個已排序的 rowid。因此在非唯一索引中,索引數據是按照索引鍵(index key)及 rowid 共同排序的。鍵值(key value)全部為 NULL 的行不會被索引,只有簇索引(cluster index)例外。在數據表中,如果兩個數據行的全部鍵值都為 NULL,也不會與唯一索引相沖突。
5.8.6.3 索引的屬性
有兩種類型的索引塊:
- 用於搜索的分支塊(branch block)
- 用於存儲索引數據的葉塊(leaf block)
5.8.6.3.1 分支塊
分支塊(branch block)中存儲以下信息:
- 最小的鍵值前綴(minimum key prefix),用於在(本塊的)兩個鍵值之間做出分支選擇
- 指向包含所查找鍵值的子塊(child block)的指針()
包含 n 個鍵值的分支塊(branch block)含有 n+1 個指針。鍵值及指針的數量同時還受索引塊(index block)容量的限制。
5.8.6.3.2 葉塊
所有葉塊(leaf block)相對於其根分支塊(root branch block)的深度(depth)是相同的。葉塊用於存儲以下信息:
- 數據行的鍵值(key value)
- 鍵值對應數據行的 ROWID
5.8.6.4 平衡樹結構的優勢
平衡樹數據結構(B-tree structure)具有以下優勢:
- 平衡樹(B-tree)內所有葉塊(leaf block)的深度相同,因此獲取索引內任何位置的數據所需的時間大致相同。
- 平衡樹索引(B-tree index)能夠自動保持平。
- 平衡樹內的所有塊容量平均在總容量的 3/4 左右。
- 在大區間(wide range)範圍內進行查詢時,無論匹配個別值(exact match)還是搜索一個區間(range search),平衡樹都能提供較好的查詢性能。
- 數據插入(insert),更新(update),及刪除(delete)的效率較高,且易於維護鍵值的順序(key order)
- 大型表,小型表利用平衡樹進行搜索的效率都較好,且搜索效率不會因數據增長而降低。
5.8.7 索引唯一掃描
索引唯一掃描(index unique scan)是效率最高的數據訪問方式之一。從平衡樹索引(B-tree index)中獲取數據時將采用此種方式。當一個唯一索引(采用平衡樹結構)的全部列都包含在查詢條件中,且查詢體條件表達式均為等號(equality)時,優化器將選擇使用索引唯一掃描。
5.8.8 索引區間掃描
當訪問選擇性較大的數據(selective data)時 Oracle 常進行索引區間掃描(index range scan)。掃描區間可以是封閉的(bounded)(兩端均封閉),也可以是不封閉的(unbounded)(一端或兩端均不封閉)。掃描所返回的數據按照索引列的升序進行排列,對於索引值相同的行將按 ROWID 的升序排列。
5.8.9 鍵壓縮
用戶利用鍵壓縮(key compression)可以將索引或索引表(index-organized table)中鍵值(column value)的部分內容進行壓縮,以便減少重復值帶來的存儲開銷。
一般來說,索引的一個鍵(key)通常由兩個片段(piece)構成:分組片段(grouping piece)及唯一片段(unique piece)。如果定義索引的鍵中不存在唯一片段,Oracle 會以 ROWID 的形式在此鍵的分組片段後添加一個唯一片段。鍵壓縮(key compression)就是將鍵的分組片段從鍵中拆分出來單獨存儲,供多個唯一片段使用。
5.8.9.1 索引鍵的前綴和後綴
鍵壓縮(key compression)將一個索引鍵拆分為前綴(prefix entry)(即分組片段(grouping piece))和後綴(suffix entry)(即唯一片段(unique piece))。壓縮是通過一個索引塊(index block)中的多個後綴共享一個前綴來實現的。在平衡樹索引(B-tree index)中只有位於葉塊(leaf block)的鍵會被壓縮。在分支塊(branch block)內不必存儲鍵的後綴,因此其中的鍵也無需壓縮。
鍵壓縮(key compression)只能在每個索引塊(index block)內分別實現,而不能跨多個索引塊。壓縮後每個索引行(index row)只保存後綴(suffix entry),而每個後綴將引用一個共享的前綴(prefix entry),後綴與其共享的前綴必須位於同一索引塊內。
默認情況下,前綴(prefix entry)由除去最後一列之外的其他鍵列(key column)構成。例如,一個索引鍵(index key)由(column1,column2,column3)3 列構成,則默認的前綴為(column1, column2)。如一組索引值為(1,2,3),(1,2,4),(1,2,7),(1,3,5),(1,3,4),(1,4,4),則其中重復出現的前綴 (1,2),(1,3) 將被壓縮。
用戶也可以手工設定前綴長度(prefix length),即前綴所包含的列數。例如,如果用戶設定前綴長度為 1,則在上述例子中,column1 為前綴,(column2,column3)為後綴,其中重復出現的前綴 1 將被壓縮。
非唯一索引(nonunique index)的最大前綴長度(prefix length)為鍵列的個數,而唯一索引(unique index)的最大前綴長度為鍵列的個數減 1。
應用鍵壓縮(key compression)後,生成索引時,如果一個鍵值(key value)的前綴(prefix entry)在索引塊(index block)中不存在,此前綴才會被寫入索引塊中。一個前綴被寫入後立即就可以被此索引塊內的後綴(suffix entry)共享,直到所有引用此前綴的後綴都被刪除為止。
5.8.9.2 性能上及存儲上的考慮
鍵壓縮(key compression)能夠節約大量存儲空間,因此用戶可以在一個索引塊(index block)內存儲更多的索引鍵(index key),從而減少 I/O,提高性能。
鍵壓縮(key compression)能夠減少索引所需的存儲空間,但索引掃描時需要重構(reconstruct)鍵值(key value),因此增加了 CPU 的負擔。此外鍵壓縮也會帶來一些存儲開銷,每個前綴(prefix entry)需要 4 字節(byte)的管理開銷。
5.8.9.3 使用鍵壓縮
鍵壓縮(key compression)在多種情況下都能夠發揮作用,例如:
- 對於非唯一索引(nonunique index),Oracle 會在每個重復的索引鍵(index key)之後添加 rowid 以便區分。如果使用了鍵壓縮,在一個索引塊(index block)內,Oracle 只需將重復的索引鍵作為前綴((prefix entry))存儲一次,並用各行的 rowid 作為後綴(suffix entry)。
- 唯一索引(nonunique index)中也存在相同的情況。例如唯一索引(stock_ticker,transaction_time)的含義是(項目,時間戳),通常數千條記錄中stock_ticker 的值是相同的,但她們對應的 transaction_time 值各不相同。使用了鍵壓縮後,一個索引塊中每個 stock_ticker 值作為前綴只需存儲一次,而各個transaction_time 值則作為後綴存儲,並引用一個共享的 stock_ticker 前綴。
- 在一個包含 VARRAY 或 NESTED TABLE 數據類型(datatype)的索引表(index-organized table)中,這些collection 類型中各個元素(element)的對象標識符(object identifier)是重復的。用戶可以使用鍵壓縮以避免重復存儲這些對象標識符。
有些情況無法使用鍵壓縮(key compression)。例如,一個只有一個索引鍵(index key)的唯一索引(unique index)就無法使用鍵壓縮,因為索引鍵中不存在可供共享的分組片段(grouping piece)。
5.8.10 逆序鍵索引
用戶可以創建逆序鍵索引(reverse key index),此處的逆序指索引列值(index key value)得各個字節(byte)按倒序排列,而非索引列(index key)逆序排列。在 RAC 環境中,使用這樣的排列方式可以避免由於對索引的修改集中在一小部分葉塊(leaf block)上而造成的性能下降。通過使索引的鍵值逆序排列,可以使插入操作分布在索引的全部葉塊中。
使用逆序鍵索引(reverse key index)後將無法對此索引進行索引區間掃描(index range scanning),因為在逆序鍵索引 中,詞匯上(lexically)相鄰的索引鍵(index key)在存儲上未必相鄰。因此在逆序鍵索引 上只能進行確定鍵掃描(fetch-by-key scan)或全索引掃描(full-index scan)。
有些情況下,使用逆序鍵索引(reverse key index)可以令 RAC 環境下的 OLTP 應用效率更高。例如,為一個 e-mail 應用中的所有郵件進行索引:由於用戶可能保存舊的郵件,因此索引必須做到既能快速訪問最新郵件,也能快速訪問舊郵件。
用戶使用 REVERSE 就可以輕易地創建逆序鍵索引(reverse key index)。在 CREATE INDEX語句中使用 REVERSE 關鍵字作為創建索引的選項:
CREATE INDEX i ON t (a,b,c) REVERSE;
用戶也可以在 REBUILD 子句後添加 NOREVERSE 關鍵字將一個逆序鍵索引(reverse key index)轉換為常規的索引:
ALTER INDEX i REBUILD NOREVERSE;
如果 REBUILD 子句後沒有使用 NOREVERSE 關鍵字,那麽逆序鍵索引(reverse key index)被重建後仍將保持逆序。
5.8.11 位圖索引
索引的目標是為用戶提供指向包含特定鍵值(key value)的數據行的指針。在常規的索引中,Oracle 將各行的鍵值及與此鍵值對應的一組 ROWID 存儲在一起,從而實現了上述目標。而在位圖索引(bitmap index)中,只需存儲每個鍵值的位圖(bitmap),而非一組 ROWID。
位圖(bitmap)中的每一位(bit)對應一個可能的 ROWID。如果某一位被置位(set),則表明著與此位對應的 ROWID 所指向的行中 包含此位所代表的鍵值(key value)。Oracle 通過一個映射函數(mapping function)將位信息轉化為實際的 ROWID,因此雖然位圖索引(bitmap index)內部的存儲結構與常規索引不同,但她同樣能實現常規索引的功能。當不同值的索引鍵的數量較少時,位圖索引的存儲效率相當高。
如果在 WHERE 子句內引用的多個列上都建有位圖索引(bitmap index),那麽進行位圖索引掃描時(bitmap indexing)可以將各個位圖索引融合在一起。不滿足全部條件的行可以被預先過濾掉。因此使用位圖索引能夠極大地提高查詢的響應時間。
5.8.11.1 數據倉庫應用中位圖索引的優勢
數據倉庫應用(data warehousing application)的特點是數據量巨大,執行的多為自定義查詢(ad hoc query),且並發事務較少。這種環境下使用位圖索引(bitmap index)具備如下優勢:
- 能夠減少大數據量自定義查詢的響應時間
- 與其他索引技術相比能夠節省大量存儲空間
- 即使硬件配置較低也能顯著提高性能
- 有利於並行 DML 和並行加載
為一個大表建立傳統的平衡樹索引(B-tree index)可能占用極大的存儲空間,索引有可能比數據表還要大數倍。而一個位圖索引(bitmap index)所占的空間比被索引數據還要小得多。
位圖索引(bitmap index)不適用於 OLTP 系統,因為這樣的系統中存在大量對數據進行修改的並發事務。位圖索引主要用於數據倉庫系統中(data warehousing)的決策支持功能,在這種環境下用戶對數據的操作主要是查詢而非修改。
主要進行大於(greater than)或小於(less than)比較的列,不適宜使用位圖索引(bitmap index)。例如,WHERE 子句中常會將 salary 列和一個值進行比較,此時更適合使用平衡樹索引(B-tree index)。位圖索引適用於等值查詢,尤其是存在 AND,OR,和 NOT 等邏輯操作符的組合時。
位圖索引(bitmap index)是集成在 Oracle 的優化器(optimizer)和執行引擎(execution engine)之中的。位圖索引也能夠和 Oracle 中的其他執行方法(execution method)無縫地組合。例如,優化器可以在利用一個表的位圖索引和另一個表的平衡樹索引(B-tree index)對這兩張表進行哈希連接(hash join)。優化器能夠在位圖索引及其他可用的訪問方法(例如常規的平衡樹索引,或全表掃描(full table scan))中選擇效率最高的方式,同時考慮是否適合使用並行執行。
位圖索引(bitmap index)如同常規索引一樣,可以結合並行查詢(parallel query)和並行 DML(parallel DML)一起工作。建立於分區表(partitioned table)的位圖索引必須為本地索引(local index)。Oracle 還支持並行地創建位圖索引,以及創建復合位圖索引。
5.8.11.2 基數
在基數(cardinality)小的列上建立位圖索引(bitmap index)效果最好。所謂某列的基數小(low cardinality)是指此列中所有不相同的值的個數要小於總行數。如果某列中所有不相同的值的個數占總行數的比例小於 1%,或某列中值的重復數量在 100 個以上,那麽就可以考慮在此列上建立位圖索引。即便某列的基數較上述標準稍大,或值的重復數量較上述標準稍小,如果在一個查詢的 WHERE 子句中需要引用此列定義復雜的條件,也可以考慮在此列上建立位圖索引。
例如,一個表包含一百萬行數據,其中的一列包含一萬個不相同的值,就可以考慮在此列上創建位圖索引(bitmap index)。此列上位圖索引的查詢性能將超過平衡樹索引(B-tree index),當此列與其他列作為組合條件時效果尤為明顯。
平衡樹索引(B-tree index)適用於高基數的數據,即數據的可能值很多,例如CUSTOMER_NAME 或 PHONE_NUMBER 列。在有些情況下,平衡樹索引所需的存儲空間可能比被索引數據還要大。如果使用得當,位圖索引將遠遠小於同等情況下的平衡樹索引。
對於自定義查詢(ad hoc query)或相似的應用,使用位圖索引(bitmap index)能夠顯著地提高查詢性能。查詢的 WHERE 子句中的 AND 和 OR 條件直接對位圖(bitmap)進行布爾運算(Boolean operation)得到一個位圖結果集(resulting bitmap),而無需將所有的位圖轉換為 ROWID。如果布爾操作後的結果集較小,那麽查詢就能夠迅速得到結果,而無需進行全表掃描(full table scan)。
5.8.11.3 位圖索引和空值
與其他大多數索引不同,位圖索引(bitmap index)可以包含鍵值(key value)為 NULL 的行。將鍵值為空的行進行索引對有些 SQL 語句是有用處的,例如包含 COUNT 聚合函數的查詢。
5.8.11.4 分區表上的位圖索引
用戶可以在分區表(partitioned table)上創建位圖索引(bitmap index)。唯一的限制是位圖索引對分區表來說必須是本地的(local),而不能是全局索引(global index)。只有非分區表才能使用全局位圖索引。
5.8.12 位圖連接索引
除了建立在單個表之上的位圖索引(bitmap index),用戶還可以創建位圖連接索引(bitmap join index),此種索引是為了連接(join)兩個或多個數據表而建的。位圖連接索引(bitmap join index)可以預先將有連接關系的數據進行保存,且所需的存儲空間較小。對於一個表的某列的每個值,位圖連接索引為其保存其他表中與此值有連接關系的數據行的 rowid。在數據倉庫環境中,連接關系通常是維表(dimension table)中的主鍵(primary key)與事實表(fact table)中的外鍵(foreign key)進行等值內連接(equi-inner join)。
物化連接視圖(materialized join view)也是一種預先將連接物化的方法,但與之相比位圖連接索引(bitmap join index)所需的存儲空間更少。因為物化連接視圖不會壓縮事實表(fact table)中的 rowid。
引用:http://blog.csdn.net/qiaqia609/article/details/10221009論索引的重要性