特征对比
同局部索引相比,由于全局索引有独立的分区规则,因此索引表中一个分区的索引值可能对应着主表的多个分区内的数据。由于索引的分区规则和主表的分区规则不一定相同,因此在分布式环境中,索引数据和主表数据存储的位置也无法保证始终在一起,这不可避免的会引入读写的 RPC 代价和分布式事务的代价。例如,当主表的分区和全局索引的分区不在同一个物理位置上, TABLE LOOKUP
算子中就会包含一次 RPC 操作到远端机器上去获取主表数据。因此全局索引相比局部索引有更高的维护代价,您应当充分评估主表的分区规则,合理的选择分区键,尽量使更多的查询条件能够覆盖主表的分区键,从而尽可能的避免使用全局索引。
使用限制
在 OceanBase 数据库当前版本中,对于有主键的表,分区键必须是主键的一部分;对于无主键的表,分区键是表中的一个普通列。由于全局索引中存储的是索引键和主键的对应关系,因此对于无主键的表,无法通过全局索引去裁剪出主表的分区,当前版本暂不支持在无主键分区表上创建全局索引。
示例如下:
obclient> CREATE TABLE t2(a int, b int) partition BY hash(a) partitions 5;
obclient> CREATE index gkey ON t2(b) global;
ERROR 1235 (0A000): create global index on table without primary key not supported
在分布式环境中,全局索引不可避免的会涉及到分布式事务和跨机的查询,因此全局索引依赖 GTS 维护全局的一致性快照,所以全局索引只能在 GTS 开启的时候使用。如果没有开启 GTS,则创建全局索引失败。
示例如下:
obclient> SET GLOBAL ob_timestamp_service=LTS;
Query OK, 0 rows affected (0.06 sec)
obclient> CREATE TABLE t1(a int, b int, PRIMARY KEY(a));
Query OK, 0 rows affected (0.17 sec)
obclient> CREATE INDEX gkey ON t1(b) PARTITION BY range(b) (PARTITION p0 VALUES LESS THAN (1), PARTITION p1 VALUES LESS THAN (2), PARTITION p2 VALUES LESS THAN(3));
ERROR 1235 (0A000): create global index when GTS is off not supported
由于 OceanBase 数据库的表是索引组织表(IOT),对于分区表而言,为了保证给定主键的查询能很快定位到表所在的分区,所以分区键必须是主键的子集。如果这个表里面还含有局部分区唯一索引(Local Partitioned Unique Index),那么分区键就必须是所有分区唯一索引列(包括主键列)交集的子集,而对于全局分区唯一索引(Global Partitioned Unique Index)并没有这个限制。
示例如下:
obclient> CREATE TABLE test(pk int,c2 int ,c3 int, PRIMARY KEY(pk)) PARTITION BY hash(pk) partitions 5;
Query OK, 0 rows affected (0.20 sec)
obclient> CREATE UNIQUE INDEX idx ON test(c2) LOCAL;
ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
obclient> CREATE UNIQUE INDEX idx ON test(c2, pk) LOCAL;
Query OK, 0 rows affected (5.34 sec)
obclient> DROP INDEX idx ON test;
Query OK, 0 rows affected (0.02 sec)
obclient> CREATE UNIQUE INDEX idx ON test(c2) GLOBAL;
Query OK, 0 rows affected (17.47 sec)