全局索引的创建规则是在索引属性中指定 GLOBAL 关键字。与局部索引相比,全局索引最大的特点是全局索引的分区规则跟表分区是相互独立的,全局索引允许指定自己的分区规则和分区个数,不一定需要跟表分区规则保持一致。
创建全局索引
如果主表没有指定分区键或者指定的分区数为 1,那么主表也只有一个分区,这个时候,全局索引的数据和主表数据的物理位置是相互绑定在一起的,无论是迁移还是副本 Leader 发生切换,它们都是作为一个整体进行变换,不会存在中间状态。如果全局索引的分区规则和主表的分区规则相同并且分区数相同,这时建议创建一个局部索引。 一方面是因为全局索引的维护代价更大;另一方面是因为全局索引无法保证和主表分区的物理位置相同,除非将其和主表指定在一个表组中。
在 Oracle 模式中,如果索引属性关键字没有指定,那么默认的索引属性是 GLOBAL 属性,即创建的索引是全局索引,并且索引表只有一个分区。示例如下:
obclient> CREATE TABLE tbl1(col1 INT,col2 INT)
PARTITION BY HASH(col2) PARTITIONS 5;
Query OK, 0 rows affected
obclient> CREATE INDEX idx1 ON tbl1(col1);
Query OK, 0 rows affected
创建全局索引
创建 Hash 分区一级分区表 tbl1_h,并为其创建采用 Range 分区的全局索引 tbl1_h_idx1。
obclient> CREATE TABLE tbl1_h(col1 INT PRIMARY KEY,col2 INT)
PARTITION BY HASH(col1) PARTITIONS 5;
Query OK, 0 rows affected
obclient> CREATE INDEX tbl1_h_idx1 ON tbl1_h(col2) GLOBAL
PARTITION BY RANGE(col2)
(PARTITION p0 VALUES LESS THAN(100),
PARTITION p1 VALUES LESS THAN(200),
PARTITION p2 VALUES LESS THAN(300)
);
Query OK, 0 rows affected
创建全局唯一索引
创建非模板化 Range + List 分区表 tbl2_f_rl,并为其创建全局唯一索引 tbl2_f_rl_idx1。
obclient> CREATE TABLE tbl2_f_rl(col1 INT,col2 INT)
PARTITION BY RANGE(col1)
SUBPARTITION BY LIST(col2)
(PARTITION p0 VALUES LESS THAN(100)
(SUBPARTITION sp0 VALUES(1,3),
SUBPARTITION sp1 VALUES(4,6),
SUBPARTITION sp2 VALUES(7,9)),
PARTITION p1 VALUES LESS THAN(200)
(SUBPARTITION sp3 VALUES(1,3),
SUBPARTITION sp4 VALUES(4,6),
SUBPARTITION sp5 VALUES(7,9))
);
Query OK, 0 rows affected
obclient> CREATE UNIQUE INDEX tbl2_f_rl_idx1 ON tbl2_f_rl(col1) GLOBAL;
Query OK, 0 rows affected
分区裁剪
全局索引的分区键一定是索引键本身,因此在使用全局索引的过程中就会指定索引分区键的查询条件,我们可以针对索引的分区规则进行分区裁剪,在查询到索引键值后可以利用索引表中存储的主键信息计算出主表的分区位置,进而对主表也能进行快速的分区定位,避免扫描主表的所有分区,因此对于无法指定主表分区键的查询而言,全局索引在一定条件下能够加速查询的检索效率。
示例如下:
obclient> EXPLAIN SELECT /*+index(t1 gkey)*/ * FROM t1 WHERE b=1\G
*************************** 1. row ***************************
Query Plan: ==========================================
|ID|OPERATOR |NAME |EST. ROWS|COST |
------------------------------------------
|0 |TABLE LOOKUP|T1 |4950 |38645|
|1 | TABLE SCAN |T1(GKEY)|4950 |1115 |
==========================================
Outputs & filters:
-------------------------------------
0 - output([T1.A], [T1.B], [T1.C]), filter(nil),
partitions(p[0-4])
1 - output([T1.A]), filter(nil),
access([T1.A]), partitions(p1)
对于上述查询,首先通过 where 条件中的 b=1 条件裁剪出全局索引的分区 p1,然后对全局索引进行 table scan 操作以得到对应的主键。利用 table lookup 算子对主表进行精确的分区扫描以避免扫描主表的所有分区。




