学习目标
- 列出不同类型的索引及其用途
- 创建各种类型的索引
- 重新组织索引
- 维护索引
- 监视索引的使用情况
- 获取索引信息
逻辑分类:
- 单列索引:索引只涉及一个列。
- 复合索引:索引涉及多个列。
- 唯一索引:确保索引列的数据唯一性。
- 非唯一索引:允许列中有重复值。
- 基于函数的索引:索引列通过某些函数进行计算。
- 域索引:支持特殊数据类型的索引(例如空间数据索引)。
物理分类:
- 分区索引:索引数据按分区进行存储。
- 非分区索引:普通的非分区索引。
- B-树索引:常见的树形索引结构。
- 反向键 B-树索引:用于解决插入热点问题。
- 位图索引:适用于低基数列的数据,使用位图进行存储。
B-Tree Index
B-Tree 索引
尽管所有类型的索引都使用 B-Tree(平衡树)结构,但“B-Tree 索引”通常指的是存储每个键对应的 ROWID(行标识符)列表的索引。
B-Tree 索引的结构
B-Tree 索引的结构类似一棵树,具有以下几个层次:
- 根节点 (Root):位于索引的顶部,包含指向下一级的条目的指针。
- 分支节点 (Branch Blocks):位于下一层,包含指向下一级的指针。
- 叶子节点 (Leaf Nodes):位于最底层,包含实际的索引条目,这些条目指向表中的行。叶子节点通过双向链接连接,使得可以按升序或降序遍历索引。
索引叶子节点条目的格式
每个索引条目由以下几个部分组成:
- 条目头 (Entry Header):存储列数和锁定信息。
- 键列长度-值对 (Key Column Length-Value Pairs):定义了索引列的大小和相应列的值。最多包含与索引列数相同的键值对。
- ROWID:指向表中行的标识符,包含键值。
B-Tree 索引叶子节点条目的特点
在非分区表的 B-Tree 索引中:
- 如果有多个行的键值相同,则会出现重复的键值,除非该索引经过压缩。
- 如果行的所有键列都为 NULL,那么该行不会有对应的索引条目。因此,使用
WHERE
子句查询 NULL 时,通常会导致全表扫描。 - 由于所有行都属于同一个段,因此使用 受限的 ROWID 来指向表中的行。
DML 操作对索引的影响
在执行 DML(数据操作语言)操作(如插入、删除、更新)时,Oracle 数据库会维护所有的索引。以下是 DML 操作对索引的影响:
- 插入操作 (Insert):插入操作会在适当的索引块中插入索引条目。
- 删除操作 (Delete):删除一行时,实际上只是逻辑删除索引条目,删除的行所占的空间不会立即用于新条目,直到该块中的所有条目都被删除。
- 更新操作 (Update):更新键列时,首先执行逻辑删除(删除旧的索引条目),然后插入新的索引条目。
PCTFREE
设置仅在创建索引时起作用,更新不会影响索引块的空闲空间。在索引块中,即使剩余空间少于PCTFREE
设置,也可以插入新的条目。
位图索引
位图索引 (Bitmap Indexes)
位图索引在某些情况下比 B-Tree 索引更具优势,尤其是在以下几种场景下:
- 低基数列:当表的某些列具有低基数(即列中只有少量不同的值),例如性别(Male/Female)或婚姻状况(Married/Single)等列时,位图索引优于 B-Tree 索引。
- 多条件查询:当查询经常使用多个
WHERE
条件,并且条件之间使用OR
连接时,位图索引能更有效地执行这些查询。 - 只读或低更新活动:当涉及的列主要是只读的,或更新活动非常少时,位图索引非常合适。
位图索引的结构
位图索引与 B-Tree 索引的结构类似,但其叶子节点存储的是每个键值的 位图,而不是 ROWID 列表。每个位图中的每一位代表一个可能的 ROWID,如果某个位被设置为 1,表示对应的行包含该键值。
位图索引的叶子节点包含以下内容:
- 条目头 (Entry Header):包含列数和锁定信息。
- 键值 (Key Values):包括键列的长度和值。比如,如果键只有一列,第一个条目的键值是 “Blue”。
- 起始 ROWID (Start ROWID):指向位图段所对应的第一行的 ROWID。
- 结束 ROWID (End ROWID):指向该位图段覆盖的最后一行的 ROWID。
- 位图段 (Bitmap Segment):由一串二进制位组成。每个位表示一行是否包含该键值(1 表示包含,0 表示不包含)。Oracle 使用专利压缩技术来存储位图段。
例如,如果位图索引中的一段位图代表一个 gender
列的值为 “Female”,则对应的位图中每一位表示某一行是否为女性。
使用位图索引
- 查找叶子节点:使用 B-Tree 索引来定位包含位图段的叶子节点。
- 定位行:根据位图中的位和 起始 ROWID,可以定位到实际的表行。
当对表中的键列进行修改时,相关的位图段必须进行更新。这将导致锁定相关的位图段,因为对整个位图段进行锁定。在锁定期间,位图所覆盖的行不能被其他事务更新,直到第一个事务完成。
Oracle 索引的分类
在 Oracle 数据库中,索引可以根据不同的标准进行分类,主要分为 逻辑分类 和 物理分类。这两类分别从索引的定义、结构、存储方式以及对查询优化的影响等方面进行区分。以下是对这些分类的详细说明:
1. 逻辑分类 (Logical Classification)
逻辑分类主要关注索引的定义和功能,而不是它是如何存储的。具体包括以下几种类型:
1.1 单列索引与复合索引 (Concatenated Index)
-
单列索引 (Single-Column Index): 这是最常见的一种索引类型,索引只涉及单一的列。通常用于查询中经常出现某个列作为条件的场景。
- 示例:
CREATE INDEX idx_emp_name ON employees (last_name);
- 示例:
-
复合索引 (Concatenated / Composite Index): 当查询条件涉及多个列时,可以创建复合索引。复合索引在查询时能够提高多个列组合的检索效率。
- 示例:
CREATE INDEX idx_emp_name_dept ON employees (last_name, department_id);
- 说明:复合索引中的列顺序非常重要,只有在查询中使用索引的前缀列时,索引才能有效。比如,
(last_name, department_id)
索引,在查询时必须先用last_name
,然后才是department_id
。
- 示例:
1.2 唯一索引 (Unique Index) 与 非唯一索引 (Nonunique Index)
-
唯一索引 (Unique Index): 保证索引列中的数据值唯一。通常用于对数据进行约束,确保没有重复值。例如,主键和唯一约束会自动创建唯一索引。
- 示例:
CREATE UNIQUE INDEX idx_emp_id ON employees (employee_id);
- 示例:
-
非唯一索引 (Nonunique Index): 索引列中的数据值不要求唯一,可以有重复的值。非唯一索引通常用于提高查询效率,尤其是用于大范围数据检索。
- 示例:
CREATE INDEX idx_emp_name ON employees (last_name);
- 示例:
1.3 基于函数的索引 (Function-Based Index)
- 基于函数的索引 (Function-Based Index): 索引的列是通过某个函数或者表达式进行计算的,而不仅仅是直接列的值。这种索引在需要基于某个计算结果进行查询时非常有效。
- 示例:
CREATE INDEX idx_upper_name ON employees (UPPER(last_name));
- 说明:这种索引适用于需要对列进行计算或转换(如大写转换、日期计算等)时,避免了在每次查询时重复计算。
- 示例:
1.4 域索引 (Domain Index)
- 域索引 (Domain Index): 特殊的索引类型,通常用于支持某些特殊数据类型的索引(例如,全文索引、空间索引等)。这种索引是通过自定义的索引结构来优化查询特定数据类型的效率。
- 例如,空间数据类型可能使用 R-tree 索引来加速地理信息的查询。
2. 物理分类 (Physical Classification)
物理分类侧重于索引的存储结构和实现方式。不同的物理索引结构影响索引的性能、存储空间以及操作方式。
2.1 分区索引与非分区索引 (Partitioned vs. Nonpartitioned Index)
-
分区索引 (Partitioned Index): 这种索引按照某个标准(例如范围、哈希等)将索引数据划分为多个分区。这对于非常大的表特别有用,可以提高查询效率,尤其是在查询涉及到数据分区时。
- 示例:
CREATE INDEX idx_emp_name ON employees (last_name) PARTITION BY RANGE (hire_date) (...);
- 示例:
-
非分区索引 (Nonpartitioned Index): 这是没有进行分区的普通索引,适用于较小或不需要分区的表。
2.2 B-树索引 (B-tree Index)
- B-树索引 (B-tree Index): 这是最常见的索引类型,适用于大部分查询,特别是范围查询。B-树索引通过树形结构来组织数据,可以高效地进行查找、插入、更新和删除操作。
-
普通 B-树索引 (Normal B-tree Index): 默认的 B-树索引,适用于大多数数据类型,支持精确查找、范围查询等。
- 示例:
CREATE INDEX idx_emp_name ON employees (last_name);
- 示例:
-
反向键 B-树索引 (Reverse Key B-tree Index): 对索引列的值进行反转,以此避免当大量数据插入时,索引的热点问题(即数据插入时集中在索引的某个位置)。这种索引主要用于减少插入时的锁竞争。
- 示例:
CREATE INDEX idx_emp_name_rev ON employees (reverse(last_name));
- 示例:
-
2.3 位图索引 (Bitmap Index)
- 位图索引 (Bitmap Index): 这种索引适用于列的数据基数低的情况(如性别、状态等),即该列只有少数不同的值(比如只有 “男” 和 “女”)。位图索引通过为每个可能的值创建一个位图来表示每行是否符合该值,从而快速进行 AND/OR 查询操作。
- 示例:
CREATE BITMAP INDEX idx_emp_gender ON employees (gender);
- 注意:位图索引不适合频繁更新的列,因为更新时需要重新生成位图。
- 示例: