為了實(shí)現(xiàn)Oracle關(guān)于增加SQL優(yōu)化查詢智能的承諾,Oracle9i增強(qiáng)了全索引SQL執(zhí)行計(jì)劃以支持基于功能的索引(function-based index)。在Oracle 8i中,SQL優(yōu)化器添加了判斷查詢是否可以專門用一個(gè)現(xiàn)存的索引來解決的智能。一旦存在索引,Oracle就會(huì)繞過對(duì)表的訪問,索引組織表(index-organized table,IOT)結(jié)構(gòu)就是一個(gè)例子。在IOT結(jié)構(gòu)中,所有的數(shù)據(jù)都載入索引的b-樹結(jié)構(gòu),這樣表(table)就成為一個(gè)多余的東西了。
一旦Oracle SQL優(yōu)化器檢測(cè)到查詢無需訪問表時(shí),Oracle就調(diào)用全索引掃描并快速讀取每一個(gè)索引塊而無需接觸表本身。有一點(diǎn)很重要:全索引掃描并沒有讀取索引節(jié)點(diǎn),而是一塊一塊的執(zhí)行掃描并快速捕獲索引節(jié)點(diǎn)。最好,Oracle調(diào)用多塊讀取功能,調(diào)用多個(gè)過程來讀取表。
Oracle和多塊讀取
為了加快表和索引的訪問速度,Oracle使用了db_file_multiblock_read_count參數(shù)(默認(rèn)參數(shù)為8)來輔助把全表掃描和全索引掃描所獲得的數(shù)據(jù)塊盡快送到數(shù)據(jù)緩沖區(qū)中。然而,這個(gè)參數(shù)只有當(dāng)SQL查詢執(zhí)行全表掃描時(shí)才可用,并且,在絕大多數(shù)情況下,查詢要使用索引來訪問表。
Oracle對(duì)全索引掃描有如下限制:
SQL請(qǐng)求的全部列(column)必須駐留在索引樹中;也就是說,SELECT和WHERE字句中的所有數(shù)據(jù)列必須存在于索引中。
查詢?cè)L問大量的行(row)。根據(jù)你查詢的范圍,比例變化范圍為10%到25%之間,這個(gè)比例參數(shù)db_file_multiblock_read_count的設(shè)置和查詢的并行程度極大的影響到這個(gè)比例。
由于索引節(jié)點(diǎn)并沒有按索引順序排列,所以列并沒有順序。這樣,ORDER BY字句將要求附加的排序操作。
Oracle提供了一個(gè)SQL提示(hint)來強(qiáng)制全索引掃描。你也可以通過指定index_ffs提示來強(qiáng)制快速索引掃描,這常常與parallel_index提示組合來提高性能。例如,下面的查詢強(qiáng)迫使用并行快速全索引掃描:
|
由于涉及了所有的變量,所以全索引是否會(huì)加快查詢速度并不能簡(jiǎn)單的加以回答。所以,大多數(shù)有經(jīng)驗(yàn)的SQL調(diào)試者(tuner)會(huì)對(duì)符合快速全索引掃描標(biāo)準(zhǔn)的查詢進(jìn)行手工計(jì)時(shí),看看使用全索引掃描的反映時(shí)間是否會(huì)降低。
函數(shù)索引基礎(chǔ)
在Oracle9i之前,全索引掃描只有當(dāng)創(chuàng)建的索引沒有空值時(shí)才可以使用,也就是說,Oracle建立索引時(shí)必須用一個(gè)NOT NULL子句才可以使用該索引。由于Oracle9i支持用函數(shù)(function-based)索引實(shí)現(xiàn)的唯索索引掃描,這種情況大大改觀。
簡(jiǎn)單回歸一下,函數(shù)索引是Oracle8的一個(gè)重要改進(jìn),因?yàn)樗峁┝艘环N有效的消除無必要長表全掃描的機(jī)制,由于函數(shù)索引可以在任何查詢語句中的WHERE子句中精確復(fù)制,Oracle總會(huì)用一個(gè)索引來匹配上SQL查詢的WHERE子句。
現(xiàn)在,我要會(huì)用一個(gè)student表來舉一個(gè)簡(jiǎn)單的例子來解釋全索引掃描如何與函數(shù)索引一起工作的過程。
創(chuàng)建student表
(student_name varchar2(40), date_of_birth date);
使用這個(gè)表,創(chuàng)建與表中所有列相關(guān)聯(lián)的函數(shù)索引。在本例中,該函數(shù)為initcap(即大寫每個(gè)單詞的首字母)和to_char(即把一個(gè)數(shù)字變成字符):
|
定義完函數(shù)索引后,Oracle9i中任何可以引用這些列(column)的SQL語句都可以使用全索引掃描。下面是SQL匹配函數(shù)索引的查詢例子:
|
用函數(shù)索引來調(diào)用全索引掃描
Oracle9i只要可能就會(huì)使用函數(shù)索引并在函數(shù)索引的基礎(chǔ)上調(diào)用全索引掃描。如果SQL優(yōu)化器統(tǒng)計(jì)結(jié)果表明使用全索引掃描的速度將會(huì)超過通過索引的b-樹訪問的速度,那么Oracle9i就會(huì)這么做。
下面是用函數(shù)索引調(diào)用唯索掃描的準(zhǔn)則。所有的SQL謂詞匹配索引中的列,查詢必須從表中返回足夠多的行,這樣做的目的是為了讓代價(jià)優(yōu)化器(cost-based optimizer)來判斷全索引掃描是否要比傳統(tǒng)的索引訪問方法要快。是否調(diào)用全索引掃描的決定取決于下面幾個(gè)參數(shù)設(shè)置:
代價(jià)優(yōu)化器的適當(dāng)統(tǒng)計(jì)數(shù)字――這個(gè)計(jì)劃(schema)最近已經(jīng)分析過了,而且optimizer_mode參數(shù)不能設(shè)置為RULE。
索引的并行程度――注意索引的并行程度是獨(dú)立設(shè)置的;索引并沒有繼承表的并行程度。
optimizer_index_cost_adj的設(shè)置――它控制代價(jià)優(yōu)化器是否傾向于全索引掃描。
db_file_multiblock_read_count的設(shè)置――這個(gè)參數(shù)影響到全索引掃描的代價(jià)。這個(gè)值越高,全索引掃描的代價(jià)也就會(huì)越“便宜”。
索引的直方圖表示――對(duì)偏移(skewed)索引,它幫助代價(jià)優(yōu)化器評(píng)估查詢返回的行數(shù)。
Oracle的一個(gè)重要提高
在函數(shù)索引基礎(chǔ)上的快速全索引掃描是Oracle9i的另一個(gè)提高性能的途徑。當(dāng)數(shù)據(jù)庫遷移到Oracle9i時(shí),許多數(shù)據(jù)庫自動(dòng)開始使用這個(gè)新的執(zhí)行計(jì)劃。不過,當(dāng)SQL代價(jià)優(yōu)化器決定是否選擇全索引掃描時(shí),還要考慮幾個(gè)因素。Oracle專業(yè)人員需要適當(dāng)設(shè)置參數(shù),以確保代價(jià)優(yōu)化器不會(huì)用不合適的方式使用快速全索引掃描――這一點(diǎn)需要特別注意。
新聞熱點(diǎn)
疑難解答
圖片精選