暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

OceanBase分布式存储管理Oracle模式全局索引

2023-04-26
281

全局索引的创建规则是在索引属性中指定 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 算子对主表进行精确的分区扫描以避免扫描主表的所有分区。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论