ORACLE索引概述(三)
空间(tablespace)中创建索引段(index segment)来存储索引的数据。用户可以通过以下方式控制索引段的空间分配和使用:
设置索引段的存储参数(storage parameter)来控制如何为此索引段分配数据扩展(extent)
为索引段设置 PCTFREE 参数,来控制组成数据扩展的各个数据块(data block)的可用空间情况。
索引段(index segment)使用的表空间(tablespace)既可以是索引所有者(owner)的默认表空间,也可以是在 CREATE INDEX 语句中指定的表空间。索引无需和其相关的表位于同一表空间中。相反,如果将索引与其相关表存储在不同磁盘上能够提升使用此索引的查询性能,因为此时 Oracle 能够并行地(parallel)访问索引及表数据。
5.8.6.1 索引块的格式
一个数据块(data block)内可用于存储索引数据的空间等于数据块容量减去数据块管理开销(overhead),索引条目管理开销(entry overhead),rowid,及记录每个索引值长度的 1 字节(byte)。
当用户创建索引时,Oracle 取得所有被索引列的数据并进行排序,之后将排序后索引值和与此值相对应的 rowid 按照从下到上的顺序加载到索引中。例如,以下语句:
CREATE INDEX employees_last_name ON employees(last_name);
Oracle 先将 employees 表按 last_name 列排序,再将排序后的 列及相应的 rowid 按从下到上的顺序加载到索引中。使用此索引时,Oracle 可以快速地搜索已排序的 last_name 值,并使用相应的 rowid 去定位包含用户所查找的 last_name 值的数据行。
5.8.6.2 索引的内部结构
Oracle 使用平衡树(B-tree)存储索引以便提升数据访问速度。当不使用索引时,用户必须对数据进行顺序扫描(sequential scan)来查找指定的值。如果有 n 行数据,那么平均需要扫描的行为 n/2。因此当数据量增长时,这种方法的开销将显著增长。
如果将一个已排序的值列(list of the values)划分为多个区间(range),每个区间的末尾包含指向下个区间的指针(pointer),而搜索树(search tree)中则保存指向每个区间的指针。此时在 n 行数据中查询一个值所需的时间为 log(n)。这就是 Oracle 索引的基本原理。
在一个平衡树索引(B-tree index)中,最底层的索引块(叶块(leaf block))存储了被索引的数据值,以及对应的 rowid。叶块之间以双向链表的形式相互连接。位于叶块之上的索引块被称为分支块(branch block),分枝块中包含了指向下层索引块的指针。如果被索引的列存储的是字符数据(character data),那么索引值为这些字符数据在当前数据库字符集(database character set)中的二进制值(binary value)。
对于唯一索引(unique index),每个索引值对应着唯一的一个 rowid。对于非唯一索引(nonunique index),每个索引值对应着多个已排序的 rowid。因此在非唯一索引中,索引数据是按照索引键(index key)及 rowid 共同排序的。键值(key value)全部为 NULL 的行不会被索引,只有簇索引(cluster index)例外。在数据表中,如果两个数据行的全部键值都为 NULL,也不会与唯一索引相冲突。
5.8.6.3 索引的属性
有两种类型的索引块:
用于搜索的分支块(branch block)
用于存储索引数据的叶块(leaf block)
5.8.6.3.1 分支块
分支块(branch block)中存储以下信息:
最小的键值前缀(minimum key prefix),用于在(本块的)两个键值之间做出分支选择
指向包含所查找键值的子块(child block)的指针()
包含 n 个键值的分支块(branch block)含有 n+1 个指针。键值及指针的数量同时还受索引块(index block)容量的限制。
5.8.6.3.2 叶块
所有叶块(leaf block)相对于其根分支块(root branch block)的深度(depth)是相同的。叶块用于存储以下信息:
数据行的键值(key value)
键值对应数据行的 ROWID
所有的 键值-ROWID 对(key and ROWID pair)都与其左右的兄弟节点(sibling)向链接(link),并按照(key,ROWID)的顺序排序。
5.8.6.4 平衡树结构的优势
平衡树数据结构(B-tree structure)具有以下优势:
平衡树(B-tree)内所有叶块(leaf block)的深度相同,因此获取索引内任何位置的数据所需的时间大致相同。
平衡树索引(B-tree index)能够自动保持平。
平衡树内的所有块容量平均在总容量的 3/4 左右。
在大区间(wide range)范围内进行查询时,无论匹配个别值(exact match)还是搜索一个区间(range search),平衡树都能提供较好的查询性能。
数据插入(insert),更新(update),及删除(delete)的效率较高,且易于维护键值的顺序(key order)
大型表,小型表利用平衡树进行搜索的效率都较好,且搜索效率不会因数据增长而降低。
5.8.7 索引唯一扫描
索引唯一扫描(index unique scan)是效率最高的数据访问方式之一。从平衡树索引(B-tree index)中获取数据时将采用此种方式。当一个唯一索引(采用平衡树结构)的全部列都包含在查询条件中,且查询体条件表达式均为等号(equality)时,优化器将选择使用索引唯一扫描。
5.8.8 索引区间扫描
当访问选择性较大的数据(selective data)时 Oracle 常进行索引区间扫描(index range scan)。扫描区间可以是封闭的(bounded)(两端均封闭),也可以是不封闭的(unbounded)(一端或两端均不封闭)。扫描所返回的数据按照索引列的升序进行排列,对于索引值相同的行将按 ROWID 的升序排列。