首批通过分布式安全可靠测评,为关键业务系统打造
全局索引
更新时间:2026-05-14 12:52:31
全局索引的创建规则是在索引属性中指定 GLOBAL 关键字。与局部索引相比,全局索引最大的特点是全局索引的分区规则跟表分区是相互独立的,全局索引允许指定自己的分区规则和分区个数,不一定需要跟表分区规则保持一致。
创建全局索引
如果主表没有指定分区键或者指定的分区数为 1,那么主表也只有一个分区,这个时候,全局索引的数据和主表数据的物理位置是相互绑定在一起的,无论是迁移还是副本 Leader 发生切换,它们都是作为一个整体进行变换,不会存在中间状态。如果全局索引的分区规则和主表的分区规则相同并且分区数相同,这时推荐创建一个局部索引。 一方面是因为全局索引的维护代价更大;另一方面是因为全局索引无法保证和主表分区的物理位置相同。
说明
创建全局索引时,如果表位于 SHARDING = 'NONE' 属性的表组中,那么创建的全局索引也一同绑定到该表组中。有关表组属性的详细信息,参见 修改表组的 SHARDING 属性。
创建全局索引
创建 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 IN(1,3),
SUBPARTITION sp1 VALUES IN(4,6),
SUBPARTITION sp2 VALUES IN(7,9)),
PARTITION p1 VALUES LESS THAN(200)
(SUBPARTITION sp3 VALUES IN(1,3),
SUBPARTITION sp4 VALUES IN(4,6),
SUBPARTITION sp5 VALUES IN(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;
+---------------------------------------------------------------+
| Query Plan |
+---------------------------------------------------------------+
| ========================================================== |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ---------------------------------------------------------- |
| |0 |DISTRIBUTED TABLE SCAN|t1(GKEY)|4950 |38645 | |
| ========================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([t1.A], [t1.B], [t1.C]), filter(nil), rowset=256 |
| access([t1.A], [t1.B], [t1.C]), partitions(p0) |
| is_index_back=true, is_global_index=true, |
| range_key([t1.B], [t1.A]), range(1,MIN ; 1,MAX), |
| range_cond([t1.B = 1]) |
+---------------------------------------------------------------+
对于上述查询,首先通过 WHERE 条件中的 b=1 条件裁剪出全局索引的分区 p1,然后对全局索引表进行 table scan 操作以得到对应的主键。利用主键对主表进行精确的分区扫描以避免扫描主表的所有分区。