索引管理
索引是一种数据库对象,它能够为表中的某一列或多个列建立一个有序的数据结构,使得数据库引擎能够快速定位到满足条件的数据行,而无需扫描整张表。创建合适的索引是数据库中提升数据检索速度的核心技术与手段。
索引创建
从索引所占据的列的数量划分,可以分为单列索引和联合索引;从索引类型上看,可分为普通索引,函数索引,唯一索引(包括主键),分区索引。oGRAC 支持上述索引类型,各种索引的创建方式如下:
基本语法
CREATE INDEX INDEX_NAME ON [Schema.]TABLE_NAME ({COLUMN_NAME | (COLUMN_NAME1, COLUMN_NAME2, ...) | EXPRESSION | FUNCTION}) [TABLESPACE TABLESPACE_NAME];INDEX_NAME:索引的名称,用户自定义,在一个表中必须是唯一的。Schema:可选参数,指定索引所属的模式(Schema),如果不指定,则默认使用当前用户的模式。TABLE_NAME:索引所属的表名。COLUMN_NAME:索引所基于的列名,创建联合索引时多个列名之间用逗号分隔。EXPRESSION:基于表达式的索引。FUNCTION:基于函数的索引。TABLESPACE OGRACSPACE:可选参数,指定索引所在的表空间,默认使用当前表空间。
示例
DROP TABLE IF EXISTS USERS;
CREATE TABLE USERS
(
ID INT CONSTRAINT PK_IDX PRIMARY KEY, -- 主键可以在创表时直接指定,其更像是一种约束
AGE INT ,
NAME VARCHAR(10),
ADDRESS VARCHAR(50),
SALARY NUMBER(20,4),
USER_ID INT
) TABLESPACE OGRACSPACE;
-- 用户可通过CREATE INDEX创建索引
CREATE INDEX AGE_IDX ON USERS(AGE) TABLESPACE OGRACSPACE; -- 单列普通索引
CREATE INDEX ADDRESS_UPPER_IDX ON USERS(UPPER(ADDRESS)) TABLESPACE OGRACSPACE; -- 函数索引
CREATE INDEX ID_AGE_IDX2 ON USERS(ID, AGE) TABLESPACE OGRACSPACE; -- 联合索引
CREATE UNIQUE INDEX USER_IDX ON USERS(USER_ID) TABLESPACE OGRACSPACE; -- 唯一索引注意:oGRAC 要求联合索引的最大列数为16。
分区索引创建
分区索引是指在分区表上创建的索引,创建方式与普通表索引相同。
CREATE TABLE orders (
order_id NUMBER,
order_date DATE,
customer_id NUMBER,
region VARCHAR2(10),
amount NUMBER
)
PARTITION BY RANGE (order_date)
SUBPARTITION BY LIST (region)
(
PARTITION p_2024_q1 VALUES LESS THAN (DATE '2024-04-01')
(SUBPARTITION p_2024_q1_east VALUES ('EAST'),
SUBPARTITION p_2024_q1_west VALUES ('WEST')),
PARTITION p_2024_q2 VALUES LESS THAN (DATE '2024-07-01')
(SUBPARTITION p_2024_q2_east VALUES ('EAST'),
SUBPARTITION p_2024_q2_west VALUES ('WEST'))
);
-- 分区表上创建普通索引
CREATE INDEX idx_order_date ON orders(order_date);
-- 分区表上创建联合索引
CREATE INDEX idx_order_date_region ON orders(order_date, region);
-- 分区表上创建唯一索引
CREATE UNIQUE INDEX idx_order_id ON orders(order_id);
-- 分区表上创建函数索引
CREATE INDEX idx_region_upper ON orders(UPPER(region));索引重建
当表发生频繁的INSERT、UPDATE、DELETE操作时,索引也会随之动态调整,导致磁盘的物理文件上存在空间碎片,索引项的逻辑顺序与物理存储顺序不一致,影响顺序扫描性能。重建索引(Index Rebuild) 就是指删除旧的索引结构,并按照原始定义重新创建一个新的、整洁的索引的过程。这个过程会重新组织索引的数据页,消除碎片,优化存储结构。用户可通过以下命令重建索引:
ALTER INDEX INDEX_NAME ON TABLE_NAME REBUILD;数据库重启回滚期间不支持重建索引。
索引修改
oGRAC 不支持修改已创建索引的结构,只允许修改已创建索引的名称。
ALTER INDEX AGE_IDX ON USERS RENAME TO AGE_IDX_NEW;
ALTER INDEX idx_order_date ON orders RENAME TO idx_order_date_new;索引删除
用户可使用DROP INDEX删除索引。数据库重启回滚期间不支持删除索引,删除表时索引会一并删除。
-- 普通表索引删除
DROP INDEX AGE_IDX ON USERS;
DROP INDEX USER_IDX ON USERS;
-- 分区表索引删除
DROP INDEX idx_order_date ON orders;
DROP INDEX idx_order_date_region ON orders;
-- 删除主键时需要通过删除约束的方式完成
ALTER TABLE USERS DROP CONSTRAINT PK_IDX;部分场景下主键约束可以不指定名称,比如:
DROP TABLE IF EXISTS TEST;
CREATE TABLE TEST(COL1 INT PRIMARY KEY, COL2 INT);该场景下可以通过ADM_INDEXES或者DB_INDEXES查看主键的名称并删除,示例如下:
SQL> SELECT INDEX_NAME FROM ADM_INDEXES WHERE TABLE_NAME = 'TEST' AND IS_PRIMARY = 'Y';
INDEX_NAME
----------------------------------------------------------------
_PK_SYS_1_27
1 rows fetched.
SQL> ALTER TABLE TEST DROP CONSTRAINT _PK_SYS_1_27;
Succeed.索引失效
用户可通过UNUSABLE命令失效索引。索引失效后,数据库不会对该表进行的增删改等操作的同时维护索引结构。如果用户后续重新启用索引,必须通过命令重建索引(重建索引后自动生效)或删除索引后重新创建。
ALTER INDEX AGE_IDX ON USERS UNUSABLE; -- 索引失效
ALTER INDEX AGE_IDX ON USERS REBUILD; -- 索引重建
ALTER INDEX idx_order_date ON orders UNUSABLE; -- 分区表索引失效
ALTER INDEX idx_order_date ON orders REBUILD; -- 分区表索引重建索引信息查看
用户可通过ADM_INDEXES或者DB_INDEXES查看索引的相关信息。
SQL> SELECT INDEX_NAME, INDEX_TYPE, TABLESPACE_NAME, IS_PRIMARY, IS_UNIQUE, COLUMNS FROM ADM_INDEXES WHERE TABLE_NAME = 'USERS';
INDEX_NAME INDEX_TYPE TABLESPACE_NAME IS_PRIMARY IS_UNIQUE COLUMNS
---------------------------------------------------------------- ---------- ---------------------------------------------------------------- ---------- --------- ----------------------------------------------------------------
PK_IDX NORMAL OGRACSPACE Y N ID
USER_IDX NORMAL OGRACSPACE N Y USER_ID
ID_AGE_IDX2 NORMAL OGRACSPACE N N ID, AGE
ADDRESS_UPPER_IDX NORMAL OGRACSPACE N N UPPER(ADDRESS)
AGE_IDX NORMAL OGRACSPACE N N AGE
5 rows fetched.
SQL> SELECT INDEX_NAME, INDEX_TYPE, TABLESPACE_NAME, IS_PRIMARY, IS_UNIQUE, COLUMNS FROM ADM_INDEXES WHERE TABLE_NAME = 'ORDERS';
INDEX_NAME INDEX_TYPE TABLESPACE_NAME IS_PRIMARY IS_UNIQUE COLUMNS
---------------------------------------------------------------- ---------- ---------------------------------------------------------------- ---------- --------- ----------------------------------------------------------------
IDX_ORDER_ID NORMAL SYSTEM N Y ORDER_ID
IDX_ORDER_DATE_REGION NORMAL SYSTEM N N ORDER_DATE, REGION
IDX_ORDER_DATE_NEW NORMAL SYSTEM N N ORDER_DATE
IDX_REGION_UPPER NORMAL SYSTEM N N UPPER(region)
4 rows fetched.INDEX_NAME:索引名称INDEX_TYPE:索引类型TABLESPACE_NAME:索引所在的表空间名称IS_PRIMARY:是否为主键索引,Y表示是,N表示否IS_UNIQUE:是否为唯一索引,Y表示是,N表示否COLUMNS:索引包含的列名,多个列名之间用逗号分隔
索引扫描方式
当前 oGRAC 支持的索引扫描方式如下:
- Index Unique Scan(唯一索引扫描):查询条件使用唯一索引的全部列的等值查询。
- Index Range Scan(索引范围扫描):非唯一索引 或 唯一索引但未提供全部列。查询条件含 =, >, >=, <, <=, BETWEEN, IN 等范围或等值操作。
- Index Full Scan(索引全扫描):通常按照索引的物理存储顺序进行扫描,不依赖查询条件。
- Index Fast Full Scan(索引快速全扫描):使用块扫描方式,并且要求查询的所有字段都包含在索引中,扫描结果是无序的,与 ORDER BY 使用索引排序时冲突、hint_no_ffs 冲突。
- Index Skip Scan(索引跳跃扫描):用于范围查询在前,等值查询在后,查询条件不包含前导第一列的查询场景。