内容主要来源于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 = 'Abbey@company.com';
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访问索引组织表。
索引组织表上的位图索引:
注意:索引组织表的行移动不会使索引组织表上的位图索引变得不可用。