內容主要來源於Oracle官方文檔(官網英文表和網絡中文版)
Oracle Database Concepts
1.索引概述
索引是一種與表或表簇相關的可選結構,有時可以提高數據的訪問速度。通過在表上的一個行或多個行上創建索引,你獲得了某些情況下從隨機分佈的錶行中檢索一小部分行的能力。索引是減小磁盤IO的手段之一。
如果一個堆組織表上沒有索引,數據庫必須通過全表掃描來查找值。
在下列情況下可以在某列上創建索引:
1.要索引的列經常被查詢,且返回行總數的一小部分;
2.在索引列上存在引用完整性約束。索引避免對父表操作時鎖定子表。
3.要在表上設置唯一鍵約束,且想手動指定索引和索引選項(名稱,表空間,存儲等);
1.1 索引特徵
索引是一種模式對象,它在邏輯上和物理上都與其相關聯的對象中的數據保持獨立。因此,索引能夠不會物理上影響表的 被創建或刪除。
刪除索引,程序仍然能正常工作,不過訪問之前被索引的數據可能變慢。
索引的存在與否,不需要改變SQL語句的寫法。索引是到一行數據的快速訪問路徑。它隻影響執行的速度。對於一個已被索引的數據值,索引直接指向包含該值行的位置。
索引被創建後,數據庫會自動維護並使用它們。表上存在過多的索引,會降低DML的性能,因爲數據庫必須更新索引。
索引具有一下屬性:
1.可用性:索引是可用或不可用的。不可用索引在DML操作中不會被維護,並會被優化程序忽略。當把一個可用索引設置爲不可用時,數據庫將刪除其索引segment;
2.可見性:索引是可見的或不可見的。不可見索引在DML操作中會被維護,但在默認情況下優化程序不會使用它。可用在 刪除索引前測試移除效果,或臨時用一下索引而不會影響整個應用程序。
鍵和列
鍵是一個列或表達式,可以在上面創建索引。鍵嚴格來講知識一個邏輯概念。
注意:主鍵和唯一鍵會自動生成索引,需要在外鍵上創建索引。
複合索引
複合索引,也叫聯合索引,是在某表中多個列上的索引。複合索引中的列應該以在檢索數據的查詢中最有意義的順序出現,但在表中不必相鄰。
如果where子句引用了複合索引中的所有列或前導列,複合索引可以加快查詢速度。一般的,經常被訪問的列放在前面。
如果前導列的基數很低,那麼數據庫可能使用索引跳躍掃描。
唯一索引和非唯一索引
索引可以是唯一的或非唯一的。唯一索引保證在表的鍵列或鍵列集上沒有具有重複值的行。非唯一索引允許在索引的列或列集中有重複的值。對於非唯一索引,rowid被包含在鍵中且以排序,因此非唯一索引按索引鍵和rowid升序進行排列。
除了位圖索引或簇鍵列值爲空的情況外,Oracle數據庫不會索引鍵列值爲空的錶行。
索引類型
B-樹索引:索引的標準類型。對於主鍵和高選擇性索引非常適合。在複合索引中使用時,B-樹索引可以按多個索引列以排序方式檢索數據。
位圖索引和位圖聯接索引:在位圖索引中,索引條目使用位圖來指向多個行。相比之下,B-樹索引條目指向單個行。位圖聯接索引是在兩個或更多個表的聯接上的位圖索引;
基於函數的索引:這種類型的索引包括經過一個函數轉換過的列或包括在表達式中的列。B-樹和位圖索引都可以是基於函數的;
應用程序索引:這種類型的索引是由用戶爲一個特定的應用程序域中的數據創建的。
1.2 B-樹索引
平衡樹簡稱B-樹,是最常見的數據庫索引類型。一個B-樹索引是被劃分爲多個範圍的已排序的值列表。通過鍵與一行或行範圍關聯起來,B-樹可以對多種類型的查詢提供優秀的檢索性能,包括精確匹配和範圍搜索等。
B-樹索引的內部結構:
分支塊和葉子塊
B-樹索引有兩種類型的塊:用於查找的分支塊和用於存儲的葉子塊。B-樹索引的上層分支塊包含指向下層索引塊的索引數據。
B-樹索引之所以是平衡的,是因爲所有葉塊都自動處於相同的深度,因此,在索引中從任意位置檢索任意記錄需要的時間基本上是相同的。索引的高度是從根塊到葉塊所需塊的數量,分支級別等於其高度減1。
分支塊用於存儲在兩個鍵之間作出分支決定所需的最小鍵前綴。這種技術使數據庫在每個分支塊上能夠儘可能存放更多的數據。分支塊包含一個指針,該指針指向包含該鍵的子塊。鍵和指針的數量受限於塊大小。
葉塊包含每個被索引的數據值,和一個相應的用來定位實際行的rowid。每個條目按照rowid、鍵排序。在一個葉塊內,鍵和rowid鏈接到其左右同級條目。這些葉塊本身也雙向鏈接在一起。
索引掃描
在索引掃描中,數據庫通過在語句中使用被索引的列,遍歷索引來檢索行。數據庫通過使用索引,使用n個IO就能找到要查的值,n是B-樹索引的高度。
如果只訪問被索引的列,那麼數據庫只需從索引中讀取值,而不用讀取表。
完全索引掃描
在完全索引掃描中,數據庫順序讀取整個索引。如果sql語句中的謂詞(where子句)引用了索引列,某些情況下也可以不指定謂詞,可能使用完全索引掃描。
完全掃描可以消除排序,因爲數據本身就是基於索引鍵排過序的。
快速完全索引掃描
快速完全索引掃描是一種完全索引掃描,數據庫並不按特定的順序讀取索引塊。數據庫僅訪問索引本身的數據,無需訪問表。
當索引包含了查詢所需的所有列,且索引鍵中至少一列具有NOT NULL 約
束時,快速完全索引掃描可以替代全表掃描。
索引範圍掃描
索引範圍掃描是對索引的有序掃描,具有以下特點:
1.在條件中指定了一個或多個索引前導列。條件指定一個或多個表達式和邏輯(布爾)運算符的組合,並返回一個值(TRUE、FALSE、UNKNOWN)。
2.一個索引鍵可能對應0個、1個或更多個值。
數據庫使用索引範圍掃描來訪問選擇性的數據。選擇性是查詢所選擇的數據佔總行數的百分比,0意味沒有任何行,1表示所有行。選擇性與一個查詢謂詞相關,比如WHERE last_name LIKE 'A%'
。值越接近0的謂詞越具有選擇性。
唯一索引掃描
唯一索引掃描必須是有0個或1個rowid與索引鍵相關聯。當一個i額謂詞使用相等運算符引用了唯一索引鍵的所有列時,數據庫將執行唯一掃描。找到第一個記錄,唯一索引掃描就停止處理,不可能有第二個記錄滿足條件。
索引跳躍掃描
索引跳躍掃描使用複合索引的邏輯子索引。數據庫跳躍地通過單個索引,好像它在多個索引中搜索一樣。如果在複合索引前導列中有少量不同值,而在非前導鍵列中有大量不同值,此時使用跳躍掃描是有益的。
當在查詢謂詞中未指定組合索引的前導列時,數據庫可能選擇索引跳躍掃描。
SELECT * FROM sh.customers WHERE cust_email = '[email protected]';
customers 表中有一列cust_gender,其值爲M 或F。假定在列
cust_gender 和cust_email 上存在一個複合索引。
索引聚簇因子
索引聚簇因子用於測量與某個索引值有關的行順序。
被索引值的行存儲的越有序,則聚簇因子越低。
如果聚簇因子較高,則在大型索引範圍掃描過程中,數據庫將執行的IO數相對較高。索引條目指向隨機表塊,因此數據庫可能必須一遍又一遍地來回重讀索引指向的同一數據塊。
如果聚簇因子較低,則大型索引範圍掃描過程中,數據庫將執行的IO數相對較低。在一個範圍內的索引鍵值傾向於指向相同的數據塊,因此該數據庫不必來回重讀相同的數據塊。
聚簇因子與索引掃描關係密切,因爲它可以顯示:
1.數據庫是會對大的範圍掃描使用索引;
2.與索引鍵相關聯的表的組織程度;
3.如果行必須按索引鍵順序排列,應該考慮使用所以組織表、分區或表簇。
例如:
上圖是僱員表中兩個數據塊的內容,行按照姓氏順序存儲在塊中。
如果在姓氏上存在一個索引,每個姓氏條目對應一個rowid,索引條目應該看起來這樣:
Abel,block1row1
Ande,block1row2
Atkinson,block1row3
Austin,block1row4
Baer,block1row5
.
.
.
同時在ID列上也有一個索引,那麼,該索引條目中僱員ID指向兩個數據塊的任意位置:
100,block1row50
101,block2row1
102,block1row9
103,block2row19
104,block2row39
105,block1row4
.
.
.
在all_indexes中第一個基於姓氏的索引應該有着較低的聚簇因子,這意味着在一個單一葉塊中的相鄰索引條目傾向於指向同一個數據塊中的行。另一個基於僱員ID的索引聚簇因子應該較高,這意味着在相同的葉塊中相鄰的索引條目不太可能指向同一個數據塊中的行。
反向鍵索引
是一種B樹索引,在物理上反轉每個索引鍵的字節,但保持列順序不變。例如如果索引鍵是20,並且在一個標準的B-樹索引中此鍵被存爲16進制的兩個字節C1 15,那麼反向鍵索引將會將其存爲 15 C1 。
反向鍵解決了在B-樹索引右側的葉塊爭用問題。在rac中,多個實例向相同的葉子塊寫入鍵值時,爭用問題很嚴重,如果使用反向鍵索引,字節順序反轉,插入時會將鍵值分散到所有的葉塊,那麼插入時的IO就被均勻的分佈在所有的葉塊。
由於索引中存儲的數據沒有按照鍵列排序,所以在某些情況下,反向鍵格式
失去了執行索引範圍掃描查詢的能力。例如如果用戶發出一個訂單id大於20的查詢,但數據庫不能從包含此ID的塊開始掃描並沿着葉塊水平推進。
升序和降序索引
對於升序索引,數據庫按照升序存儲數據。默認情況下,字符數據按字符中每個字節的二進制值排序,數值數據按照從小到大排序,日期數據按照從早到晚排序。
通過在CREATE INDEX語句中指定DESC關鍵字,可以創建降序索引。
當查詢按一些列升序,一些列降序排序時,降序索引很有用。例如,last_name和department_id上創建一個複合索引:
CREATE INDEX emp_name_dpt_ix ON hr.employees(last_name ASC, department_id DESC);
當查詢要求按照姓氏升序,按照部門降序排序,數據庫可以使用此索引檢索數據,避免額外排序步驟。
鍵壓縮
數據使用鍵壓縮來壓縮B-樹索引或索引組織表中的主鍵列值部分。鍵壓縮可以大大減少索引所使用的空間。
通常索引鍵有兩個片,一個分組片和一個唯一片。鍵壓縮將鍵值分爲兩個部分:分組片的前綴條目,唯一片或近乎唯一片的後綴條目。數據庫通過在多個後綴條目間共享前綴條目來實現壓縮。
注意:如果一個鍵未被定義爲唯一片,那麼數據庫會將一個rowid加到分組片中以提供一個唯一片。
默認情況下,一個唯一索引的前綴有出最後一列之外的所有鍵列組成,非唯一索引的前綴包含所有鍵列。
例子:加入在oe.orders 表上創建一個複合索引:
CREATE INDEX orders_mod_stat_ix ON orders ( order_mode, order_status );
如果兩個索引鍵列order_mode和order_status有重複的值,那麼索引條目可能如下所示:
online,0,AAAPvCAAFAAAAFaAAa
online,0,AAAPvCAAFAAAAFaAAg
online,0,AAAPvCAAFAAAAFaAAl
online,2,AAAPvCAAFAAAAFaAAm
online,3,AAAPvCAAFAAAAFaAAq
online,3,AAAPvCAAFAAAAFaAAt
由於是非唯一索引,鍵前綴是order_mode和order_status的串聯值。如果此索引按默認鍵壓縮創建,那麼重複前綴將會被壓縮,如下所示:
online,0
AAAPvCAAFAAAAFaAAa
AAAPvCAAFAAAAFaAAg
AAAPvCAAFAAAAFaAAl
online,2
AAAPvCAAFAAAAFaAAm
online,3
AAAPvCAAFAAAAFaAAq
AAAPvCAAFAAAAFaAAt
可以指定前綴索引的長度。如果指定了前綴長度爲1,那麼前綴會使order_mode,後綴將會是order_status,rowid。壓縮時,索引會提取重複出現的online作爲前綴,如下:
online
0,AAAPvCAAFAAAAFaAAa
0,AAAPvCAAFAAAAFaAAg
0,AAAPvCAAFAAAAFaAAl
2,AAAPvCAAFAAAAFaAAm
3,AAAPvCAAFAAAAFaAAq
3,AAAPvCAAFAAAAFaAAt
對索引中的每個葉塊,一個特定前綴最多被存儲一次。只有在B-樹索引的葉塊中的鍵會被壓縮。在分支塊中的鍵後綴可以被截斷,但不會被壓縮。
1.3 位圖索引
網上的位圖索引結構圖:
在位圖索引中,數據庫爲每個索引鍵存儲一個位圖。在傳統的B-樹索引中,一個索引條目指向單個行。在位圖索引中,每個索引鍵存儲指向多個行的指針。
位圖索引主要用於數據倉庫或以特定方式引用很多列的查詢環境。以下情況可能需要一個位圖索引:
1.索引列的基數較低,也就是說不同值的數目相比表的總行數很小。
2.被索引的表是隻讀的或DML語句不會對其進行重大修改。
位圖中的每一位對應一個可能的rowid。如果設置了某位,對應rowid的行包含該鍵值。映射函數將位的位置轉換爲一個實際的rowid,所以,雖然位圖索引使用不同的內部表示形式,但提供了與B-樹索引相同的功能。
如果更新了索引列的一行,數據庫將鎖住整個索引鍵條目,而不僅僅是位映射到的被修改的行。由於一個鍵指向多行,對索引數據的DML會鎖住所有行,因此位圖索引不適合OLTP應用。
單表位圖索引
示例:以客戶表爲示例瞭解原理
如上圖所示,cust_marital_status列和cust_gender有較低的基數,而cust_id 和 cust_last_name 的基數較高。因此,在cust_marital_status 和 cust_gender列上創建位圖索引可能是恰當的。而在其他列上創建位圖則可能沒什麼用處,在這些列上創建B-樹唯一索引可能提供高效的檢索性能。
對於下面的位圖索引: cust_gender 列的位圖索引,包含針對每個性別的單獨位圖
映射函數將位圖中的每一位轉換爲客戶表中的一個rowid。每一位的值取決於表中的相應行的值。見結構圖好理解一點。另外,位圖索引的鍵可以使null
位圖聯接索引
位圖聯接索引是建立在兩個或更多表的聯接之上的位圖索引。對於表列中的每個值,索引存儲被索引表中的相應行的rowid。
示例:
一個查詢:
SELECT COUNT(*)
FROM employees, jobs
WHERE employees.job_id = jobs.job_id
AND jobs.job_title = 'Accountant';
如果想從索引本身中檢索數據,而不是從表中掃描,可以創建位圖聯接索引:
CREATE BITMAP INDEX employees_bm_idx
ON employees (jobs.job_title)
FROM employees, jobs
WHERE employees.job_id = jobs.job_id;
**如下圖 :**索引鍵是jobs.job_title,被索引表是employees;
位圖聯接索引employees_bm_idx 中的鍵是jobs.job_title ,它指向employees表中的行,當需要對account這個職業計數是不需要掃描employees表,從位圖聯接索引中取就可以,索引中包含需要的信息。
位圖存儲結構
數據庫使用一個B-樹索引結構來爲每個索引鍵存儲視圖。
假設jobs.job_title列具有Shipping Clerk, Stock Clerk和其他幾個唯一值,該索引的位圖條目由以下幾部分組成:
1.job_title 作爲索引鍵
2.一個rowid範圍的低值和高值
3.一個指定rowid範圍的位圖
一個索引葉塊中能包含的幾個條目如下:
Shipping Clerk,AAAPzRAAFAAAABSABQ,AAAPzRAAFAAAABSABZ,0010000100
Shipping Clerk,AAAPzRAAFAAAABSABa,AAAPzRAAFAAAABSABh,010010
Stock Clerk,AAAPzRAAFAAAABSAAa,AAAPzRAAFAAAABSAAc,1001001100
Stock Clerk,AAAPzRAAFAAAABSAAd,AAAPzRAAFAAAABSAAt,0101001001
Stock Clerk,AAAPzRAAFAAAABSAAu,AAAPzRAAFAAAABSABz,100001
.
.
.
由於rowid的範圍不同,相同的job_title可以出現在多個條目中。
假定某個會話更新了一名僱員的job_id,從Shipping Clerk到
Stock Clerk。在這種情況下,會話需要對新值和舊值的索引鍵條目獨佔訪問。數據庫鎖定這兩種條目指向的行,不會鎖定其他鍵指向的行,直到update語句提交。
位圖索引的數據被存儲在一個段中。數據庫在一個或多個片中存儲每個位圖。每個片佔據單個塊的一部分
1.4 基於函數的索引
你能基於函數或一列多列的表達式創建索引。一個基於函數的索引計算函數或表達式的值,並把它存儲在索引中。基於函數的索引既可以是B-樹索引也可以是位圖索引。
生成索引的函數可以是算術表達式或者包含sql函數,用戶定義plsql函數,包含數,C調用的表達式。例如兩列相加作爲函數。
基於函數索引的使用
基於函數的索引對於where子句中包含函數計算的語句是有效的。數據庫只對包含在查詢裏面的函數使用函數索引。當數據庫處理insert和update語句時,必須同步處理計算函數。
例如創建了基於算術表達式的索引:
CREATE INDEX emp_total_sal_idx
ON employees (12 * salary * commission_pct, salary, commission_pct);
當執行如下查詢時,數據庫使用前面的索引:
SELECT employee_id, last_name, first_name,
12*salary*commission_pct AS "ANNUAL SAL"
FROM employees
WHERE (12 * salary * commission_pct) < 30000
ORDER BY "ANNUAL SAL" DESC;
Plan Hash Value : 1122513885
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 160 | 2 | 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 5 | 160 | 2 | 00:00:01 |
| * 2 | INDEX RANGE SCAN DESCENDING | EMP_TOTAL_SAL_IDX | 1 | | 1 | 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 2 - access(12*"SALARY"*"COMMISSION_PCT"<30000)
EMPLOYEE_ID | LAST_NAME | FIRST_NAME | ANNUAL SAL |
---|---|---|---|
159 | Smith | Lindsey | 28800 |
151 | Bernstein | David | 28500 |
152 | Hall | Peter | 27000 |
160 | Doran | Louise | 27000 |
175 | Hutton | Alyssa | 26400 |
149 | Zlotkey | Eleni | 25200 |
169 | Bloom | Harrison | 24000 |
又例如創建了基於sql函數的索引:
CREATE INDEX emp_fname_uppercase_idx
ON employees ( UPPER(first_name) );
數據庫執行如下查詢時會使用索引:
SELECT *
FROM employees
WHERE UPPER(first_name) = 'AUDREY';
Plan Hash Value : 3842569606
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 69 | 2 | 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 1 | 69 | 2 | 00:00:01 |
| * 2 | INDEX RANGE SCAN | EMP_FNAME_UPPERCASE_IDX | 1 | | 1 | 00:00:01 |
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 2 - access(UPPER("FIRST_NAME")='AUDREY')
優化基於函數的索引
對於在where子句中包含一個表達式的查詢,優化器可以使用基於函數索引的索引範圍掃描。當where子句的選擇性低的時候,範圍掃描的訪問路徑特別有優勢。例如:如果一個索引建立在表達式12*salary*commission_pct
上,優化器可以使用索引範圍掃描。
虛擬列是有用的,對於快速訪問表達式生成的數據。例如:你能對12*salary*commission_pct
定義一個虛擬列annual_sal ,並且能在虛擬列annual_sal 上創建一個基於函數的索引。
優化器通過解析SQL語句中的表達式,然後比較語句的表達式樹和基於函數的索引來執行表達式匹配。這種比較不區分大小寫,並且忽略空格。
1.5 應用程序域索引
應用程序域索引是一個指向應用程序的自定義索引。Oracle提供了可擴展的索引以執行以下操作:
1.可以在自定義的,非結構話的數據類型,例如文檔、空間數據、圖片和視頻剪輯上建立索引;
2.使用專門的索引技術
您可以將特定於應用程序的索引管理例程封裝爲indextype模式對象,並在對象類型的表列或屬性上定義域索引。可擴展索引可以有效地處理特定於應用程序的操作符。
被稱爲墨盒的應用程序軟件控制域索引的結構和內容。數據庫與應用程序交互以構建、維護和搜索域索引。索引結構本身可以作爲索引組織的表存儲在數據庫中,也可以作爲文件存儲在外部
1.6 索引存儲
數據庫在索引段中存儲所以數據。數據塊中的索引數據可用空間是數據塊大小減去塊頭、條目頭、rowid和每個索引值的一個字節。
索引段的表空間要麼是用戶的默認表空間,要麼是CREATE INDEX語句中指定的表空間。爲了便於管理,可以將索引存儲在與表不同的表空間。例如,可以選擇不備份僅包含索引的表空間,這些索引可以重新構建,從而減少備份所需的時間和存儲。
2.索引組織表概述
索引組織表是存儲在B-樹索引結構變體中的表。在堆組織表中,行被插入到合適的位置。在索引組織表中,行被存儲在定義在表上的主鍵索引中,B-樹中的每個索引條目還存儲非鍵列的值,因此,索引就是數據,數據就是索引。應用程序通過使用sql語句,向操作堆組織表那樣操作索引組織表。
2.1 索引組織表特徵
數據庫通過操作B-樹索引,來執行索引組織表上的所有操作。
堆組織表與索引組織表的比較:
堆組織表 | 索引組織表 |
---|---|
有rowid唯一標識行,主鍵約束可以選擇 | 主鍵唯一標識行,必須有主鍵約束 |
ROWID僞列中的物理rowid允許創建輔助索引 | ROWID僞列中的邏輯rowid允許創建輔助索引 |
可直接由rowid訪問行 | 可直接通過主鍵訪問行 |
順序全表掃描按一定順序返回所有行 | 完全索引掃描或快速索引掃描按一定順序返回所有行 |
能與其他表存儲在表簇中 | 不能存儲在表簇中 |
可以包含一個LONG類型的列和多個LOB類型的列 | 可以包含LOB列,不能包含LONG列 |
可以包含虛擬列(只支持關係堆表) | 不能包含虛擬列 |
索引組織表departments的結構:
葉塊包含的錶行按照主鍵順序排列:第一個葉塊中的第一個值顯示 部門ID爲20、部門名稱爲Marketing、經理ID爲201、位置ID爲1800。
索引組織表將所有的數據都存儲在相同的結構中,且不需要存儲rowid。上圖中的葉塊1中的條目按主鍵排序後存儲如下:
20,Marketing,201,1800
30,Purchasing,114,1700
葉塊2包含如下條目:
50,Shipping,121,1500
60,IT,103,1400
讀取時,按照主鍵順序對索引組織表掃描,依照葉塊1、葉塊2 的順序訪問。
如果此時departments是堆表,表段中的數據塊1 如下:
50,Shipping,121,1500
20,Marketing,201,1800
數據塊2如下:
30,Purchasing,114,1700
60,IT,103,1400
此堆組織表的B-樹索引的一個葉塊包含如下條目,第一列爲主鍵,第二列爲rowid:
20,AAAPeXAAFAAAAAyAAD
30,AAAPeXAAFAAAAAyAAA
50,AAAPeXAAFAAAAAyAAC
60,AAAPeXAAFAAAAAyAAB
那麼按主鍵順序掃描表,讀取順序爲:塊1、塊2、塊1、塊2,IO數是索引組織表中的兩倍。
2.2 索引組織表的行溢出區
在創建一個索引組織表時,您可以指定一個單獨的段爲行溢出區。索引組織表的B-樹索引條目可能比較大,因爲它們包含整個行,因此用一個單獨的
段來包含這些條目是很有用的。相比之下,常規B-樹條目則通常很小,因
爲它們僅包含鍵和rowid。
如果指定了行溢出區,那麼數據庫可以將索引組織的表中的行分成以下兩個部分:
1.索引條目:包含所有主鍵列值、指向該行溢出部分的物理rowid、或者幾個非鍵列值。這部分存儲在索引段中。
2.溢出部分:包含剩餘的非鍵列的值。這部分存儲在溢出區段中。
創建示例:
CREATE TABLE admin_docindex(
token char(20),
doc_id NUMBER,
token_frequency NUMBER,
token_offsets VARCHAR2(2000),
CONSTRAINT pk_admin_docindex PRIMARY KEY (token, doc_id))
ORGANIZATION INDEX
TABLESPACE admin_tbs
PCTTHRESHOLD 20
OVERFLOW TABLESPACE admin_tbs2;
2.3 索引組織表的輔助索引
輔助索引是一個建立在索引組織表上的索引。它是一個索引的索引。輔助索引是一個獨立的模式對象,與索引組織表分開存儲。
數據庫使用邏輯rowid作爲行標識符來訪問索引組織表。邏輯的rowid是表主鍵的base64編碼表示形式。邏輯rowid的長度取決於主鍵長度。
對索引組織表執行插入操作時,索引葉塊中的行可以在塊內或塊之間移動。索引組織表中的行不像堆表中的行那樣遷移。因爲索引組織表中的行沒有永久的物理地址,數據庫使用基於主鍵的邏輯rowid。
例如:如果departments是索引組織表。location_id存儲麼個部門的位置id。表像如下存儲行,最後一個值是位置id:
10,Administration,200,1700
20,Marketing,201,1800
30,Purchasing,114,1700
40,Human Resources,203,2400
在location_id上的輔助索引可能有如下索引條目,逗號後是邏輯rowid(基於主鍵生成的):
1700,*BAFAJqoCwR/+
1700,*BAFAJqoCwQv+
1800,*BAFAJqoCwRX+
2400,*BAFAJqoCwSn+
輔助索引提供多索引組織表的快速和高效的訪問,使用的列既不是主鍵,也不是主鍵前綴。例如當需查詢位置ID大於1700的部門名稱時,可以使用該輔助索引加快訪問。
邏輯rowid 和 物理猜測
輔助索引使用邏輯rowid來查找行。邏輯rowid包括一個物理猜測,物理猜測是索引條目第一次被創建是的物理rowid。數據庫可以使用物理猜測繞過主鍵,之間探入索引組織表的葉塊。當行的物理位置更改,即使包含的物理猜測已經過時,其邏輯rowid仍然有效。
對於堆組織表,使用輔助索引訪問包含一個對輔助索引的掃描和一個取得包含行的數據塊的額外IO。
對於索引組織表,使用輔助索引訪問依賴於物理猜測的使用和準確性:
1.不使用物理猜測時,訪問兩個索引掃描:先是輔助索引,接着是主鍵索引;
2.使用物理猜測,訪問取決與物理猜測的準確性:如果準確,訪問包括一個輔助索引掃描和一個讀取行所在數據塊的額外IO;如果不準確,訪問包括一個輔助索引和一個讀取錯誤的數據塊IO,接着是按住鍵對索引組織表的唯一索引掃描。
索引組織表上的位圖索引
索引組織表上的輔助索引可以是位圖索引。位圖索引爲每個索引鍵存儲一個位圖。
當索引組織表上存在位圖索引時,所偶位圖索引都使用堆組織映射表。映射表存儲索引組織表的邏輯rowid。每個映射行會爲相應的索引組織錶行存儲一個邏輯rowid。
數據庫使用搜索鍵訪問位圖索引。如果數據庫找到該鍵,那麼對應的位圖索引條目轉換爲一個物理rowid。對於堆表,數據庫使用物理rowid訪問基表。對索引組織表,數據庫使用物理rowid訪問映射表,從而生成邏輯rowid,數據庫通過邏輯rowid訪問索引組織表。
索引組織表上的位圖索引:
注意:索引組織表的行移動不會使索引組織表上的位圖索引變得不可用。