带你认识Oracle索引类型(全面总结)
Oracle索引和MySQL索引是一個(gè)概念,都是為了提高數(shù)據(jù)庫查詢效率,例如字典的目錄,就是一種索引。不同的索引有不同的查詢效率,比如字典的目錄有以拼音首字母的,有偏旁部首的。當(dāng)我們對(duì)所有索引類型有了了解之后,就可以針對(duì)性的寫出高效的SQL語句、建立最合適的索引。
那Oracle索引都有哪些類型呢?
首先我們來看一下索引的數(shù)據(jù)結(jié)構(gòu):B樹
在介紹之前,首先建立一張表
create table test(id number,a number,b number,c number ); alter table test add constraint pk_test primary key (id) using index;插入數(shù)據(jù)
begin for i in 1 .. 100000 loopinsert into testvalues(i,mod(i,2),mod(i,20000),mod(i,20000));end loop;commit; end;表建好了,有一個(gè)主鍵id,和三個(gè)值a、b、c。
下面開始我們的表演
INDEX UNIQUE SCAN索引唯一掃描
看下面這個(gè)SQL語句
select id from test where id = 5000;我們知道id是主鍵,具有唯一性,而上述語句的SQL是一個(gè)等值條件(id=400,而<、>、>=等都屬于非等值條件),所以該語句執(zhí)行的索引為INDEX UNIQUE SCAN,這個(gè)速度是最快的。
條件:主鍵等值查詢
INDEX RANGE SCAN索引范圍掃描
看下面這個(gè)SQL
select id from test where id<5000;這個(gè)屬于主鍵上的非等值查詢條件,走的就是索引范圍掃描,當(dāng)然還包括非主鍵索引情況。
下面我們?cè)籴槍?duì)a、b、c建立兩個(gè)索引:
第一個(gè)索引是一個(gè)a和b的復(fù)合索引,第二個(gè)索引建立在c上。
我們看下面這個(gè)SQL
該語句也會(huì)走索引范圍掃描。
你是否有疑問,我們?nèi)绾沃勒Z句是走哪種索引的?這可以從Oracle的執(zhí)行計(jì)劃看到,查看Oracle的執(zhí)行計(jì)劃只需要將你要觀察的索引加入到其監(jiān)控中。
條件:主鍵非等值查詢、非主鍵查詢。
INDEX FULL SCAN索引全掃描
對(duì)于表來說,有全表掃描。對(duì)于索引來說,也存在全索引掃描,與全表掃描非常類似。索引掃描只在CBO模式下起作用。
什么是CBO模式?這就不得不說Oracle的兩種優(yōu)化器:
RBO:Rule-Based Optimization,Oracle 10g版本后被棄用,RBO是基于預(yù)先設(shè)定好的語法優(yōu)先級(jí)對(duì)語法進(jìn)行執(zhí)行計(jì)劃的優(yōu)化,所以開發(fā)者必須非常了解RBO的規(guī)則,這種方式非常呆板,因?yàn)槠渲徽J(rèn)規(guī)則。
CBO:Cost-Based Optimization,Oracle 8引入,Oracle 10g取代了RBO,根據(jù)SQL執(zhí)行情況的統(tǒng)計(jì)信息來對(duì)SQL的執(zhí)行計(jì)劃進(jìn)行優(yōu)化,這部分是Oracle公司保密的。問過Oracle公司的講師說也不清楚具體細(xì)節(jié)。
這種方式有個(gè)特點(diǎn),會(huì)自動(dòng)對(duì)數(shù)據(jù)進(jìn)行排序。省去了全表掃描后,再進(jìn)行order by的操作。
因?yàn)锽樹索引本身就是排序好的,默認(rèn)是ASC升序,可以在創(chuàng)建索引的時(shí)候進(jìn)行指定。但是Oracle的執(zhí)行計(jì)劃會(huì)自動(dòng)針對(duì)升序的降序查詢進(jìn)行優(yōu)化,那么為什么要存在降序操作?答案是:在復(fù)合索引上,可以對(duì)(a desc,b asc),滿足一定的業(yè)務(wù)場(chǎng)景。
我們看下面這個(gè)SQL
因?yàn)榕判虻臈l件只有id,并且id已經(jīng)建立索引,所以執(zhí)行計(jì)劃會(huì)被優(yōu)化成INDEX FULL SCAN。
條件:表和表進(jìn)行連接查詢,查詢語句中有order by,group by并且子句所有列都在索引中(聯(lián)合索引)
小tip:如何看oracle的執(zhí)行計(jì)劃?sqlplus也可,但當(dāng)然還有更好的方式,我用的Navicat,執(zhí)行完sql后,可以通過它的“解釋”功能看執(zhí)行計(jì)劃,走的什么索引類型,走的哪個(gè)索引。
INDEX FAST FULL SCAN快速全表掃描
快速全表掃描是掃描索引中的所有數(shù)據(jù)塊,與全表掃描比,區(qū)別就是其不進(jìn)行排序,即在這種方式下,返回的數(shù)據(jù)不是以排序的形式。可以多塊讀、并行讀。所以叫FAST。
看下面的語句
這個(gè)語句有兩個(gè)特點(diǎn),第一:返回值a和b都在索引上,第二:查詢條件也在索引上。這條語句通過B樹索引查詢到rowid后,不需要額外在去原來的表里查數(shù)據(jù)了。為什么呢?回憶一下,符合索引包括根、枝、葉,葉子上存儲(chǔ)的是索引值,包括:rowid、鍵值、鍵值長度、所屬標(biāo)號(hào)。看到?jīng)],如果所取的值都在索引上,就可以直接返回了,如果是
select a,b,c from test where b<1000;這樣返回值多了一個(gè)c,并不在復(fù)合索引上,所以還會(huì)用查到的rowid,去原表中取c的值,這樣就不會(huì)走INDEX FAST FULL SCAN了。
INDEX SKIP SCAN索引跳躍掃描
這個(gè)也很簡單,在復(fù)合索引中,可能會(huì)有如下類型數(shù)據(jù):
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 0 | 4 |
| 0 | 5 |
| 0 | 6 |
| … | … |
可以看b的值是不同的,a的取值只有0和1。索引跳躍掃描是掃描意思呢?就是當(dāng)在這樣一種a,b取值的情況下,對(duì)a和b建復(fù)合索引,oracle的優(yōu)化器會(huì)將其優(yōu)化成兩個(gè)索引,分別是當(dāng)a=0,a=1時(shí)的索引。
那么我們?cè)赼,b上建聯(lián)合索引,仿佛有些問題。理論上不會(huì)在這樣的一個(gè)沒有多大區(qū)分度的a值上建索引的,所以一般看到INDEX SKIP SCAN,其一般開銷都很大。
INDEX COMBINE索引組合掃描
當(dāng)一個(gè)查詢語句中,有兩個(gè)查詢,這兩個(gè)查詢列對(duì)應(yīng)兩個(gè)索引值。這種情況下就會(huì)出現(xiàn)索引組合掃描。比如:
select * from test where b<1000 and c>200;ps,這里假設(shè)我們對(duì)b和c分別建立的索引。
走INDEX COMBINE會(huì)比單獨(dú)走b或c的索引,開銷都要小。
有心人是否看到,這個(gè)sql要取的值是所有,并非b或c。那么如果取的b或c呢?看下面的
INDEX JOIN索引聯(lián)立
select b,c from test where b<1000 and c>200;這種情況就是所查詢的值在索引上,可以直接返回,不在用查到的rowid回原表取數(shù)據(jù)的情況。
嚴(yán)格來說,INDEX COMBINE和INDEX JOIN都不能算是一種獨(dú)立的索引,只是對(duì)開頭的5種索引的一種優(yōu)化或補(bǔ)充。
到這里7種索引類型都介紹完了,留一個(gè)疑問
INDEX FAST FULL SCAN一定比INDEX FULL SCAN要快嗎?
總結(jié)
以上是生活随笔為你收集整理的带你认识Oracle索引类型(全面总结)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: turbo编译码c语言,Turbo码的编
- 下一篇: kettle下载百度网盘地址含入门教程6