索引在各種關系型數據庫系統中都是舉足輕重的組成部分,其對于提高檢索數據的速度起至關重要的作用。在Oracle中,索引基本分為以下幾種:B*Tree索引,反向索引,降序索引,位圖索引,函數索引,interMedia全文索引等。本文主要就前6種索引進行分析,由于interMedia全文索引涉及的內容可以單獨寫一篇文章,所以不在此對其做分析。
首先給出各種索引的簡要解釋:
b*tree index:幾乎所有的關系型數據庫中都有b*tree類型索引,也是被最多使用的。其樹結構與二叉樹比較類似,根據rid快速定位所訪問的行。
反向索引:反轉了b*tree索引碼中的字節,是索引條目分配更均勻,多用于并行服務器環境下,用于減少索引葉的競爭。
降序索引:8i中新出現的索引類型,針對逆向排序的查詢。
位圖索引:使用位圖來管理與數據行的對應關系,多用于OLAP系統。
函數索引:這種索引中保存了數據列基于function返回的值,在select * from table where function(column)=value這種類型的語句中起作用。
2 各種索引的結構分析
2.1 B*Tree索引B*Tree索引是最常見的索引結構,默認建立的索引就是這種類型的索引。B*Tree索引在檢索高基數數據列(高基數數據列是指該列有很多不同的值)時提供了最好的性能。當取出的行數占總行數比例較小時B-Tree索引比全表檢索提供了更有效的方法。但當檢查的范圍超過表的10%時就不能提高取回數據的性能。B-Tree索引是基于二叉樹的,由分支塊(branch block)和葉塊(leaf block)組成。在樹結構中,位于最底層底塊被稱為葉塊,包含每個被索引列的值和行所對應的rowid。在葉節點的上面是分支塊,用來導航結構,包含了索引列(關鍵字)范圍和另一索引塊的地址。
假設我們要找索引中值為80的行,從索引樹的最上層入口開始,定位到大于等于50,然后往左找,找到第2個分支塊,定位為75-100,最后再定位到葉塊上,找到80所對應的rowid,然后根據rowid去讀取數據塊獲取數據。如果查詢條件是范圍選擇的,比如where column >20 and column <80,那么會先定位到第一個包含20的葉塊,然后橫向查找其他的葉塊,直到找到包含80的塊為止,不用每次都從入口進去再重新定位。
2.2 反向索引
反向索引是B*Tree索引的一個分支,它的設計是為了運用在某些特定的環境下的。Oracle推出它的主要目的就是為了降低在并行服務器(Oracle Parallel Server)環境下索引葉塊的爭用。當B*Tree索引中有一列是由遞增的序列號產生的話,那么這些索引信息基本上分布在同一個葉塊,當用戶修改或訪問相似的列時,索引塊很容易產生爭用。反向索引中的索引碼將會被分布到各個索引塊中,減少了爭用。反向索引反轉了索引碼中每列的字節,通過dump()函數我們可以清楚得看見它做了什么。舉個例子:1,2,3三個連續的數,用dump()函數看它們在Oracle內部的表示方法。
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->
SQL
>
select
'
number
'
,
dump
(
1
,
16
)
from
dual
2
union
all
select
'
number
'
,
dump
(
2
,
16
)
from
dual
3
union
all
select
'
number
'
,
dump
(
3
,
16
)
from
dual;
'
NUMBE DUMP(1,16) ------ ----------------- number Typ=2 Len=2: c1,2 (1) number Typ=2 Len=2: c1,3 (2) number Typ=2 Len=2: c1,4 (3) 再對比一下反向以后的情況: SQL> select
'
number
'
,dump(reverse(1),16) from dual 2 union all select
'
number
'
,dump(reverse(2),16) from dual 3 union all select
'
number
'
,dump(reverse(3),16) from dual;
'
NUMBE
DUMP
(
REVERSE
(
1
),
1
--
---- -----------------
number
Typ
=
2
Len
=
2
:
2
,c1 (
1
)
number
Typ
=
2
Len
=
2
:
3
,c1 (
2
)
number
Typ
=
2
Len
=
2
:
4
,c1 (
3
)
我們發現索引碼的結構整個顛倒過來了,這樣1,2,3個索引碼基本上不會出現在同一個葉塊里,所以減少了爭用。不過反向索引又一個缺點就是不能在所有使用常規索引的地方使用。在范圍搜索中其不能被使用,例如,where column>value,因為在索引的葉塊中索引碼沒有分類,所以不能通過搜索相鄰葉塊完成區域掃描。
2.3 降序索引
降序索引是8i里面新出現的一種索引,是B*Tree的另一個衍生物,它的變化就是列在索引中的儲存方式從升序變成了降序,在某些場合下降序索引將會起作用。舉個例子,我們來查詢一張表并進行排序:
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->
SQL
>
select
*
from
test
where
a
between
1
and
100
order
by
a
desc
,b
asc
; 已選擇100行。 Execution
Plan
--
--------------------------------------------------------
0
SELECT
STATEMENT Optimizer
=
CHOOSE (Cost
=
2
Card
=
100
Bytes
=
400
)
1
0
SORT(
ORDER
BY
)(Cost
=
2
Card
=
100
Bytes
=
400
)
2
1
INDEX
(RANGE SCAN)
OF
'
IND_BT
'
(NON
-
UNIQUE
) (Cost
=
2
Card
=
100
Bytes
=
400
)
這里優化器首先選擇了一個索引范圍掃描,然后還有一個排序的步驟。如果使用了降序索引,排序的過程會被取消。
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->
SQL
>
create
index
test.ind_desc
on
test.testrev(a
desc
,b
asc
); 索引已創建。 SQL
>
analyze
index
test.ind_desc
compute
statistics
; 索引已分析
再來看下執行路徑:
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->
SQL
>
select
*
from
test
where
a
between
1
and
100
order
by
a
desc
,b
asc
; 已選擇100行。 Execution
Plan
(SQL執行計劃,稍后會講解如何使用)。
--
--------------------------------------------------------
0
SELECT
STATEMENT Optimizer
=
CHOOSE (Cost
=
2
Card
=
100
Bytes
=
400
)
1
0
INDEX
(RANGE SCAN)
OF
'
IND_DESC
'
(NON
-
UNIQUE
) (Cost
=
2
Card
=
100
Bytes
=
400
)
我們看到排序過程消失了,這是因為創建降序索引時Oracle已經把數據都按降序排好了。另外一個需要注意的地方是要設置init.ora里面的compatible參數為8.1.0或以上,否則創建時desc關鍵字將被忽略。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

