Oracle索引详解
Oracle索引
- 一、索引介紹
- 1、什么是索引?
- 2、使用索引的目的
- 二、索引的分類及結(jié)構(gòu)
- 1、邏輯上:
- 2、物理上:
- 三、各種索引詳解
- 1、 B樹(shù)索引
- (1)特點(diǎn):
- (2)技巧:
- 2、位圖索引
- (1)特點(diǎn):
- (2)技巧:
- 3、 反向索引
- (1)特點(diǎn):
- (2)技巧:
- 4、HASH索引
- (1)特點(diǎn):
- 5、函數(shù)索引
- 6、分區(qū)索引和全局索引
- 7、域索引 Domain
- 四、怎樣建立索引
- 1、普通索引
- 2、唯一索引
- 3、位圖索引
- 4、組合索引
- 5、基于函數(shù)索引
- 6、反向鍵索引
- 7.重置索引
- 8.刪除索引
- 五、索引失效細(xì)節(jié)
- 1.使用不等于操作符(<>, !=)
- 2.使用 is null 或 is not null
- 3.使用函數(shù)
- 4.比較不匹配的數(shù)據(jù)類型
- 5.使用like子句
- 6.使用in
- 7.如果能不用到排序,則盡量避免排序
一、索引介紹
1、什么是索引?
??索引是建立在表的一列或多個(gè)列上的輔助對(duì)象,目的是加快訪問(wèn)表中的數(shù)據(jù);Oracle存儲(chǔ)索引的數(shù)據(jù)結(jié)構(gòu)是B樹(shù),位圖索引也是如此,只不過(guò)是葉子節(jié)點(diǎn)不同B數(shù)索引;索引由根節(jié)點(diǎn)、分支節(jié)點(diǎn)和葉子節(jié)點(diǎn)組成,上級(jí)索引塊包含下級(jí)索引塊的索引數(shù)據(jù),葉節(jié)點(diǎn)包含索引數(shù)據(jù)和確定行實(shí)際位置的rowid。
2、使用索引的目的
??當(dāng)查詢返回的記錄數(shù)排序表<40%非排序表 <7%且表的碎片較多(頻繁增加、刪除)時(shí)可以加快查詢速度減少I(mǎi)/O操作消除磁盤(pán)排序
二、索引的分類及結(jié)構(gòu)
1、邏輯上:
Single column/Concatenated 單行索引/多行索引
Unique/NonUnique 唯一索引/非唯一索引
2、物理上:
B-tree B樹(shù)索引
Bitmap 位圖索引
REVERSE 反向索引
HASHHASH索引
Function-based基于函數(shù)的索引
Partitioned/NonPartitioned 分區(qū)索引/非分區(qū)索引
Domain 域索引
三、各種索引詳解
1、 B樹(shù)索引
??Oracle數(shù)據(jù)庫(kù)中最常見(jiàn)的索引類型是b-tree索引,也就是B-樹(shù)索引,以其同名的計(jì)算科學(xué)結(jié)構(gòu)命名。CREATE INDEX語(yǔ)句時(shí),默認(rèn)就是在創(chuàng)建b-tree索引。沒(méi)有特別規(guī)定可用于任何情況。
(1)特點(diǎn):
??適合與大量的增、刪、改(OLTP)
??不能用包含OR操作符的查詢;
??適合高基數(shù)的列(唯一值多)
??典型的樹(shù)狀結(jié)構(gòu);
??每個(gè)結(jié)點(diǎn)都是數(shù)據(jù)塊;
??大多都是物理上一層、兩層或三層不定,邏輯上三層;
??葉子塊數(shù)據(jù)是排序的,從左向右遞增;
??在分支塊和根塊中放的是索引的范圍;
(2)技巧:
??索引列的值都存儲(chǔ)在索引中。因此,可以建立一個(gè)組合(復(fù)合)索引,這些索引可以直接滿足查詢,而不用訪問(wèn)表。這就不用從表中檢索數(shù)據(jù),從而減少了I/O量。
2、位圖索引
??位圖索引非常適合于決策支持系統(tǒng)(Decision Support System,DSS)和數(shù)據(jù)倉(cāng)庫(kù),它們不應(yīng)該用于通過(guò)事務(wù)處理應(yīng)用程序訪問(wèn)的表。它們可以使用較少到中等基數(shù)(不同值的數(shù)量)的列訪問(wèn)非常大的表。盡管位圖索引最多可達(dá)30個(gè)列,但通常它們都只用于少量的列。
例如,您的表可能包含一個(gè)稱為Sex的列,它有兩個(gè)可能值:男和女。這個(gè)基數(shù)只為2,如果用戶頻繁地根據(jù)Sex列的值查詢?cè)摫?#xff0c;這就是位圖索引的基列。當(dāng)一個(gè)表內(nèi)包含了多個(gè)位圖索引時(shí),您可以體會(huì)到位圖索引的真正威力。如果有多個(gè)可用的位圖索引,Oracle就可以合并從每個(gè)位圖索引得到的結(jié)果集,快速刪除不必要的數(shù)據(jù)。
(1)特點(diǎn):
??適合與決策支持系統(tǒng);
??做UPDATE代價(jià)非常高;
??非常適合OR操作符的查詢;
??基數(shù)比較少的時(shí)候才能建位圖索引;
(2)技巧:
??對(duì)于有較低基數(shù)的列需要使用位圖索引。性別列就是這樣一個(gè)例子,它有兩個(gè)可能值:男或女(基數(shù)僅為2)。位圖對(duì)于低基數(shù)(少量的不同值)列來(lái)說(shuō)非???#xff0c;這是因?yàn)樗饕某叽缦鄬?duì)于B樹(shù)索引來(lái)說(shuō)小了很多。因?yàn)檫@些索引是低基數(shù)的B樹(shù)索引,所以非常小,因此您可以經(jīng)常檢索表中超過(guò)半數(shù)的行,并且仍使用位圖索引。
??當(dāng)大多數(shù)條目不會(huì)向位圖添加新的值時(shí),位圖索引在批處理(單用戶)操作中加載表(插入操作)方面通常要比B樹(shù)做得好。當(dāng)多個(gè)會(huì)話同時(shí)向表中插入行時(shí)不應(yīng)該使用位圖索引,在大多數(shù)事務(wù)處理應(yīng)用程序中都會(huì)發(fā)生這種情況。
??在一個(gè)查詢中合并多個(gè)位圖索引后,可以使性能顯著提高。位圖索引使用固定長(zhǎng)度的數(shù)據(jù)類型要比可變長(zhǎng)度的數(shù)據(jù)類型好。較大尺寸的塊也會(huì)提高對(duì)位圖索引的存儲(chǔ)和讀取性能。
3、 反向索引
??這個(gè)索引不常見(jiàn),但是特定情況特別有效,比如一個(gè)varchar(5)位字段(員工編號(hào))含值
(10001,10002,10033,10005,10016…)
這種情況默認(rèn)索引分布過(guò)于密集,不能利用好服務(wù)器的并行
但是反向之后10001,20001,33001,50001,61001就有了一個(gè)很好的分布,能高效的利用好并行運(yùn)算。
(1)特點(diǎn):
??不可以將反轉(zhuǎn)鍵索引與位圖索引或索引組織表結(jié)合使用。因?yàn)椴荒軐?duì)位圖索引和索引組織表進(jìn)行反轉(zhuǎn)鍵處理。
(2)技巧:
??如果您的磁盤(pán)容量有限,同時(shí)還要執(zhí)行大量的有序載入,就可以使用反轉(zhuǎn)鍵索引。
4、HASH索引
??使用HASH索引必須要使用HASH集群。建立一個(gè)集群或HASH集群的同時(shí),也就定義了一個(gè)集群鍵。這個(gè)鍵告訴Oracle如何在集群上存儲(chǔ)表。在存儲(chǔ)數(shù)據(jù)時(shí),所有與這個(gè)集群鍵相關(guān)的行都被存儲(chǔ)在一個(gè)數(shù)據(jù)庫(kù)塊上。如果數(shù)據(jù)都存儲(chǔ)在同一個(gè)數(shù)據(jù)庫(kù)塊上,并且將HASH索引作為WHERE子句中的確切匹配,Oracle就可以通過(guò)執(zhí)行一個(gè)HASH函數(shù)和I/O來(lái)訪問(wèn)數(shù)據(jù)——而通過(guò)使用一個(gè)二元高度為4的B樹(shù)索引來(lái)訪問(wèn)數(shù)據(jù),則需要在檢索數(shù)據(jù)時(shí)使用4個(gè)I/O。其中的查詢是一個(gè)等價(jià)查詢,用于匹配HASH列和確切的值。Oracle可以快速使用該值,基于HASH函數(shù)確定行的物理存儲(chǔ)位置。
??HASH索引可能是訪問(wèn)數(shù)據(jù)庫(kù)中數(shù)據(jù)的最快方法,但它也有自身的缺點(diǎn)。集群鍵上不同值的數(shù)目必須在創(chuàng)建HASH集群之前就要知道。需要在創(chuàng)建HASH集群的時(shí)候指定這個(gè)值。低估了集群鍵的不同值的數(shù)字可能會(huì)造成集群的沖突(兩個(gè)集群的鍵值擁有相同的HASH值)。這種沖突是非常消耗資源的。沖突會(huì)造成用來(lái)存儲(chǔ)額外行的緩沖溢出,然后造成額外的I/O。如果不同HASH值的數(shù)目已經(jīng)被低估,您就必須在重建這個(gè)集群之后改變這個(gè)值。
??ALTER CLUSTER命令不能改變HASH鍵的數(shù)目。HASH集群還可能浪費(fèi)空間。如果無(wú)法確定需要多少空間來(lái)維護(hù)某個(gè)集群鍵上的所有行,就可能造成空間的浪費(fèi)。如果不能為集群的未來(lái)增長(zhǎng)分配好附加的空間,HASH集群可能就不是最好的選擇。如果應(yīng)用程序經(jīng)常在集群表上進(jìn)行全表掃描,HASH集群可能也不是最好的選擇。由于需要為未來(lái)的增長(zhǎng)分配好集群的剩余空間量,全表掃描可能非常消耗資源。
在實(shí)現(xiàn)HASH集群之前一定要小心。您需要全面地觀察應(yīng)用程序,保證在實(shí)現(xiàn)這個(gè)選項(xiàng)之前已經(jīng)了解關(guān)于表和數(shù)據(jù)的大量信息。通常,HASH對(duì)于一些包含有序值的靜態(tài)數(shù)據(jù)非常有效。
(1)特點(diǎn):
??可以在表中創(chuàng)建基于函數(shù)的索引。如果沒(méi)有基于函數(shù)的索引,任何在列上執(zhí)行了函數(shù)的查詢都不能使用這個(gè)列的索引。例如,下面的查詢就不能使用JOB列上的索引,除非它是基于函數(shù)的索引:
select * from emp where UPPER(job) = 'MGR';下面的查詢使用JOB列上的索引,但是它將不會(huì)返回JOB列具有Mgr或mgr值的行:
select * from emp where job = 'MGR';??可以創(chuàng)建這樣的索引,允許索引訪問(wèn)支持基于函數(shù)的列或數(shù)據(jù)。可以對(duì)列表達(dá)式UPPER(job)創(chuàng)建索引,而不是直接在JOB列上建立索引,如:
create index EMP$UPPER_JOB on emp(UPPER(job));??盡管基于函數(shù)的索引非常有用,但在建立它們之前必須先考慮下面一些問(wèn)題:
能限制在這個(gè)列上使用的函數(shù)嗎?如果能,能限制所有在這個(gè)列上執(zhí)行的所有函數(shù)嗎
??是否有足夠應(yīng)付額外索引的存儲(chǔ)空間?
??在每列上增加的索引數(shù)量會(huì)對(duì)針對(duì)該表執(zhí)行的DML語(yǔ)句的性能帶來(lái)何種影響?
??基于函數(shù)的索引非常有用,但在實(shí)現(xiàn)時(shí)必須小心。在表上創(chuàng)建的索引越多,INSERT、UPDATE和DELETE語(yǔ)句的執(zhí)行就會(huì)花費(fèi)越多的時(shí)間。
5、函數(shù)索引
??可以在表中創(chuàng)建基于函數(shù)的索引。如果沒(méi)有基于函數(shù)的索引,任何在列上執(zhí)行了函數(shù)的查詢都不能使用這個(gè)列的索引。例如,下面的查詢就不能使用JOB列上的索引,除非它是基于函數(shù)的索引:
select * from emp where UPPER(job) = 'MGR';下面的查詢使用JOB列上的索引,但是它將不會(huì)返回JOB列具有Mgr或mgr值的行:
select * from emp where job = 'MGR';??可以創(chuàng)建這樣的索引,允許索引訪問(wèn)支持基于函數(shù)的列或數(shù)據(jù)??梢詫?duì)列表達(dá)式UPPER(job)創(chuàng)建索引,而不是直接在JOB列上建立索引,如:
create index EMP$UPPER_JOB on emp(UPPER(job));盡管基于函數(shù)的索引非常有用,但在建立它們之前必須先考慮下面一些問(wèn)題:
??能限制在這個(gè)列上使用的函數(shù)嗎?如果能,能限制所有在這個(gè)列上執(zhí)行的所有函數(shù)嗎
??是否有足夠應(yīng)付額外索引的存儲(chǔ)空間?
??在每列上增加的索引數(shù)量會(huì)對(duì)針對(duì)該表執(zhí)行的DML語(yǔ)句的性能帶來(lái)何種影響?
基于函數(shù)的索引非常有用,但在實(shí)現(xiàn)時(shí)必須小心。在表上創(chuàng)建的索引越多,INSERT、UPDATE和DELETE語(yǔ)句的執(zhí)行就會(huì)花費(fèi)越多的時(shí)間。
6、分區(qū)索引和全局索引
??分區(qū)索引就是簡(jiǎn)單地把一個(gè)索引分成多個(gè)片斷。通過(guò)把一個(gè)索引分成多個(gè)片斷,可以訪問(wèn)更小的片斷(也更快),并且可以把這些片斷分別存放在不同的磁盤(pán)驅(qū)動(dòng)器上(避免I/O問(wèn)題)。B樹(shù)和位圖索引都可以被分區(qū),而HASH索引不可以被分區(qū)??梢杂泻脦追N分區(qū)方法:表被分區(qū)而索引未被分區(qū);表未被分區(qū)而索引被分區(qū);表和索引都被分區(qū)。不管采用哪種方法,都必須使用基于成本的優(yōu)化器。分區(qū)能夠提供更多可以提高性能和可維護(hù)性的可能性
有兩種類型的分區(qū)索引:本地分區(qū)索引和全局分區(qū)索引。每個(gè)類型都有兩個(gè)子類型,有前綴索引和無(wú)前綴索引。表各列上的索引可以有各種類型索引的組合。如果使用了位圖索引,就必須是本地索引。把索引分區(qū)最主要的原因是可以減少所需讀取的索引的大小,另外把分區(qū)放在不同的表空間中可以提高分區(qū)的可用性和可靠性。
??在使用分區(qū)后的表和索引時(shí),Oracle還支持并行查詢和并行DML。這樣就可以同時(shí)執(zhí)行多個(gè)進(jìn)程,從而加快處理這條語(yǔ)句。
??可以使用與表相同的分區(qū)鍵和范圍界限來(lái)對(duì)本地索引分區(qū)。每個(gè)本地索引的分區(qū)只包含了它所關(guān)聯(lián)的表分區(qū)的鍵和ROWID。本地索引可以是B樹(shù)或位圖索引。如果是B樹(shù)索引,它可以是唯一或不唯一的索引。
??這種類型的索引支持分區(qū)獨(dú)立性,這就意味著對(duì)于單獨(dú)的分區(qū),可以進(jìn)行增加、截取、刪除、分割、脫機(jī)等處理,而不用同時(shí)刪除或重建索引。Oracle自動(dòng)維護(hù)這些本地索引。本地索引分區(qū)還可以被單獨(dú)重建,而其他分區(qū)不會(huì)受到影響。
7、域索引 Domain
??域索引實(shí)際為用戶自定義索引,域索引主要對(duì)存儲(chǔ)在數(shù)據(jù)庫(kù)中的媒體,圖像數(shù)據(jù)進(jìn)行索引,這些數(shù)據(jù)在oracle中基本上以BLOB類型存儲(chǔ),不同的應(yīng)用存儲(chǔ)格式也不同,oracle不可能提供某一種現(xiàn)成的算法對(duì)這些數(shù)據(jù)進(jìn)行索引,為了能夠?qū)@些類型數(shù)據(jù)快速訪問(wèn),oracle提供了現(xiàn)成的接口函數(shù),用戶可以針對(duì)自己的數(shù)據(jù)格式實(shí)現(xiàn)這些接口函數(shù),以達(dá)到對(duì)這些數(shù)據(jù)的快速訪問(wèn)。
四、怎樣建立索引
CREATE UNIQUE | BITMAP INDEX <schema>.<index_name>ON <schema>.<table_name>(<column_name> | <expression> ASC | DESC,<column_name> | <expression> ASC | DESC,...)TABLESPACE <tablespace_name>STORAGE <storage_settings>LOGGING | NOLOGGINGCOMPUTE STATISTICSNOCOMPRESS | COMPRESS<nn>NOSORT | REVERSEPARTITION | GLOBAL PARTITION<partition_setting> UNIQUE | BITMAP:指定UNIQUE為唯一值索引,BITMAP為位圖索引,省略為B-Tree索引。
<column_name> | <expression> ASC | DESC:可以對(duì)多列進(jìn)行聯(lián)合索引,當(dāng)為expression時(shí)即“基于函數(shù)的索引”
TABLESPACE:指定存放索引的表空間(索引和原表不在一個(gè)表空間時(shí)效率更高)
STORAGE:可進(jìn)一步設(shè)置表空間的存儲(chǔ)參數(shù)
LOGGING | NOLOGGING:是否對(duì)索引產(chǎn)生重做日志(對(duì)大表盡量使用NOLOGGING來(lái)減少占用空間并提高效率)
COMPUTE STATISTICS:創(chuàng)建新索引時(shí)收集統(tǒng)計(jì)信息
NOCOMPRESS | COMPRESS<nn>:是否使用“鍵壓縮”(使用鍵壓縮可以刪除一個(gè)鍵列中出現(xiàn)的重復(fù)值)
NOSORT | REVERSE:NOSORT表示與表中相同的順序創(chuàng)建索引,REVERSE表示相反順序存儲(chǔ)索引值
PARTITION | NOPARTITION:可以在分區(qū)表和未分區(qū)表上對(duì)創(chuàng)建的索引進(jìn)行分區(qū)
1、普通索引
create index index_text_txt on test(txt);2、唯一索引
create unique index <index_name> on <table_name>(<coiumn_name>);3、位圖索引
create bitmap index <index_name> on <table_name>(<column_name>)4、組合索引
create index <index_name> on <table_name>(<column_name1><column_name2>)5、基于函數(shù)索引
create index <index_name> on <table_name>(column_name) reverse; create index <index_name> on <table_name>(upper(column_name))6、反向鍵索引
create index <index_name> on <table_name>(column_name) reverse;7.重置索引
alter index <index_name> rebuild;8.刪除索引
drop index <index_name>五、索引失效細(xì)節(jié)
1.使用不等于操作符(<>, !=)
??下面這種情況,即使在列dept_id有一個(gè)索引,查詢語(yǔ)句仍然執(zhí)行一次全表掃描
select * from dept where staff_num <> 1000;??但是開(kāi)發(fā)中的確需要這樣的查詢,難道沒(méi)有解決問(wèn)題的辦法了嗎?
??有!
??通過(guò)把用 or 語(yǔ)法替代不等號(hào)進(jìn)行查詢,就可以使用索引,以避免全表掃描:上面的語(yǔ)句改成下面這樣的,就可以使用索引了。
2.使用 is null 或 is not null
??使用 is null 或is nuo null也會(huì)限制索引的使用,因?yàn)閿?shù)據(jù)庫(kù)并沒(méi)有定義null值。如果被索引的列中有很多null,就不會(huì)使用這個(gè)索引(除非索引是一個(gè)位圖索引,關(guān)于位圖索引,會(huì)在以后的blog文章里做詳細(xì)解釋)。在sql語(yǔ)句中使用null會(huì)造成很多麻煩。
解決這個(gè)問(wèn)題的辦法就是:建表時(shí)把需要索引的列定義為非空(not null)
3.使用函數(shù)
??如果沒(méi)有使用基于函數(shù)的索引,那么where子句中對(duì)存在索引的列使用函數(shù)時(shí),會(huì)使優(yōu)化器忽略掉這些索引。下面的查詢就不會(huì)使用索引:
select * from staff where trunc(birthdate) = '01-MAY-82';??但是把函數(shù)應(yīng)用在條件上,索引是可以生效的,把上面的語(yǔ)句改成下面的語(yǔ)句,就可以通過(guò)索引進(jìn)行查找。
select * from staff where birthdate < (to_date('01-MAY-82') + 0.9999);4.比較不匹配的數(shù)據(jù)類型
??比較不匹配的數(shù)據(jù)類型也是難于發(fā)現(xiàn)的性能問(wèn)題之一。下面的例子中,dept_id是一個(gè)varchar2型的字段,在這個(gè)字段上有索引,但是下面的語(yǔ)句會(huì)執(zhí)行全表掃描。
select * from dept where dept_id = 900198;??這是因?yàn)閛racle會(huì)自動(dòng)把where子句轉(zhuǎn)換成to_number(dept_id)=900198,就是3所說(shuō)的情況,這樣就限制了索引的使用。把SQL語(yǔ)句改為如下形式就可以使用索引
select * from dept where dept_id = '900198';5.使用like子句
??使用like子句查詢時(shí),數(shù)據(jù)需要把所有的記錄都遍歷來(lái)進(jìn)行判斷,索引不能發(fā)揮作用,這種情況也要盡量避免。
Like 的字符串中第一個(gè)字符如果是‘%’則用不到索引
Column1 like ‘a(chǎn)aa%’ 是可以的
Column1 like ‘%aaa%’用不到
6.使用in
??盡管In寫(xiě)法要比exists簡(jiǎn)單一些,exists一般來(lái)說(shuō)性能要比In要高的多
用In還是用Exists的時(shí)機(jī),當(dāng)in的集合比較小的時(shí)候,或者用Exists無(wú)法用到選擇性高的索引的時(shí)候,用In要好,否則就要用Exists
例:
??假定TEST表的dt字段是date類型的并且對(duì)dt建了索引。
??如果要查‘20041010’一天的數(shù)據(jù).下面的方法用不到索引
7.如果能不用到排序,則盡量避免排序
??用到排序的情況有集合操作。Union ,minus ,intersect等,注:union all 是不排序的。Order by、Group by、Distinct、In 有時(shí)候也會(huì)用到排序,確實(shí)要排序的時(shí)候也盡量要排序小數(shù)據(jù)量,盡量讓排序在內(nèi)存中執(zhí)行,有文章說(shuō),內(nèi)存排序的速度是硬盤(pán)排序的1萬(wàn)倍。
總結(jié)
以上是生活随笔為你收集整理的Oracle索引详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Cocos2d-x 3.17.2 集成X
- 下一篇: Kettle文件下载