為了實現Oracle關於增加SQL優化查詢智能的承諾,Oracle9i增強了全索引SQL執行計劃以支持基於功能的索引(function-based index)。在Oracle8中,SQL優化器添加了判斷查詢是否可以專門用一個現存的索引來解決的智能。一旦存在索引,Oracle就會繞過對表的訪問,索引組織表(index-organized table,IOT)結構就是一個例子。在IOT結構中,所有的數據都載入索引的b-樹結構,這樣表(table)就成為一個多余的東西了。
一旦Oracle SQL優化器檢測到查詢無需訪問表時,Oracle就調用全索引掃描並快速讀取每一個索引塊而無需接觸表本身。有一點很重要:全索引掃描並沒有讀取索引節點,而是一塊一塊的執行掃描並快速捕獲索引節點。最好,Oracle調用多塊讀取功能,調用多個過程來讀取表。
Oracle和多塊讀取
為了加快表和索引的訪問速度,Oracle使用了db_file_multiblock_read_count參數(默認參數為8)來輔助把全表掃描和全索引掃描所獲得的數據塊盡快送到數據緩沖區中。然而,這個參數只有當SQL查詢執行全表掃描時才可用,並且,在絕大多數情況下,查詢要使用索引來訪問表。
Oracle對全索引掃描有如下限制:
SQL請求的全部列(column)必須駐留在索引樹中;也就是說,SELECT和WHERE字句中的所有數據列必須存在於索引中。
查詢訪問大量的行(row)。根據你查詢的范圍,比例變化范圍為10%到25%之間,這個比例參數db_file_multiblock_read_count的設置和查詢的並行程度極大的影響到這個比例。
由於索引節點並沒有按索引順序排列,所以列並沒有順序。這樣,ORDER BY字句將要求附加的排序操作。
Oracle提供了一個SQL提示(hint)來強制全索引掃描。你也可以通過指定index_ffs提示來強制快速索引掃描,這常常與parallel_index提示組合來提高性能。例如,下面的查詢強迫使用並行快速全索引掃描:
select distinct /*+ index_ffs(c,pk_auto) parallel_index_ (automobile, pk_auto) color, count(*) from automobiles group by color;
由於涉及了所有的變量,所以全索引是否會加快查詢速度並不能簡單的加以回答。所以,大多數有經驗的SQL調試者(tuner)會對符合快速全索引掃描標准的查詢進行手工計時,看看使用全索引掃描的反映時間是否會降低。
在Oracle9i之前,全索引掃描只有當創建的索引沒有空值時才可以使用,也就是說,Oracle建立索引時必須用一個NOT NULL子句才可以使用該索引。由於Oracle9i支持用函數(function-based)索引實現的唯索索引掃描,這種情況大大改觀。
簡單回歸一下,函數索引是Oracle8的一個重要改進,因為它提供了一種有效的消除無必要長表全掃描的機制,由於函數索引可以在任何查詢語句中的WHERE子句中精確復制,Oracle總會用一個索引來匹配上SQL查詢的WHERE子句。
現在,我要會用一個student表來舉一個簡單的例子來解釋全索引掃描如何與函數索引一起工作的過程。
創建student表:
(student_name varchar2(40), date_of_birth date);
使用這個表,創建與表中所有列相關聯的函數索引。在本例中,該函數為initcap(即大寫每個單詞的首字母)和to_char(即把一個數字變成字符):
create index whole_student on student (initcap(student_name), to_char(date_of_birth,’MM-DD-YY’));
定義完函數索引後,Oracle9i中任何可以引用這些列(column)的SQL語句都可以使用全索引掃描。下面是SQL匹配函數索引的查詢例子:
select * from student where initcap(student_name) = ‘Jones’; select * from student where to_char(date_of_birth,’MM-DD=YY’) = ’04-07-85’;
用函數索引來調用全索引掃描
Oracle9i只要可能就會使用函數索引並在函數索引的基礎上調用全索引掃描。如果SQL優化器統計結果表明使用全索引掃描的速度將會超過通過索引的b-樹訪問的速度,那麼Oracle9i就會這麼做。
下面是用函數索引調用唯索掃描的准則。所有的SQL謂詞匹配索引中的列,查詢必須從表中返回足夠多的行,這樣做的目的是為了讓代價優化器(cost-based optimizer)來判斷全索引掃描是否要比傳統的索引訪問方法要快。是否調用全索引掃描的決定取決於下面幾個參數設置:
代價優化器的適當統計數字——這個計劃(schema)最近已經分析過了,而且optimizer_mode參數不能設置為RULE。
索引的並行程度——注意索引的並行程度是獨立設置的;索引並沒有繼承表的並行程度。optimizer_index_cost_adj的設置——它控制代價優化器是否傾向於全索引掃描。db_file_multiblock_read_count的設置——這個參數影響到全索引掃描的代價。這個值越高,全索引掃描的代價也就會越“便宜”。索引的直方圖表示——對偏移(skewed)索引,它幫助代價優化器評估查詢返回的行數。
Oracle的一個重要提高
在函數索引基礎上的快速全索引掃描是Oracle9i的另一個提高性能的途徑。當數據庫遷移到Oracle9i時,許多數據庫自動開始使用這個新的執行計劃。不過,當SQL代價優化器決定是否選擇全索引掃描時,還要考慮幾個因素。Oracle專業人員需要適當設置參數,以確保代價優化器不會用不合適的方式使用快速全索引掃描——這一點需要特別注意。