局部索引又名分区索引,创建索引的分区关键字是 LOCAL。局部索引的分区键等同于表的分区键,局部索引的分区数等同于表的分区数,所以局部索引的分区机制和表的分区机制一样。
下述示例语句为给分区表 t1 创建一个局部索引 idx:
obclient> CREATE TABLE t1(a int primary key, b int) PARTITION BY hash(a) partitions 5;
obclient> CREATE INDEX idx ON t1(b) local;
局部索引是针对单个分区上的数据创建的索引,因此局部索引的索引键值跟表中的数据是一一对应的关系,即局部索引上的一个分区一定对应到一个表分区,它们具有相同的分区规则,因此对于局部唯一索引而言,它只能保证分区内部的唯一性,而无法保证表数据的全局唯一性。如果要使用局部唯一索引去对数据唯一性做约束,那么局部唯一索引中必须包含表分区键。
下述示例语句为给分区表 t2 创建局部唯一索引 uk:
obclient> CREATE TABLE t2(a int primary key, b int) PARTITION BY hash(a) partitions 5;
obclient> CREATE UNIQUE INDEX uk ON t2(b) LOCAL;
ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
obclient> CREATE UNIQUE INDEX uk2 on t2(b, a) local;
Query OK, 0 rows affected (5.32 sec)
在 OceanBase 中,局部索引同样支持分区裁剪。使用分区裁剪的前提条件是查询条件中能够指定分区键,可以减少在查询过程中读取的分区个数,从而能够提高查询检索的效率。下述示例语句为查询条件中指定分区键:
obclient> EXPLAIN SELECT /*+index(t1 idx)*/ b FROM t1 WHERE b=1 AND a=1\G
*************************** 1. row ***************************
Query Plan: =====================================
|ID|OPERATOR |NAME |EST. ROWS|COST|
-------------------------------------
|0 |TABLE GET|t1(idx)|1 |52 |
=====================================
Outputs & filters:
-------------------------------------
0 - output([t1.b]), filter(nil),
access([t1.b]), partitions(p1)
1 row in set (0.01 sec)
如果在查询中,没有指定分区键,那么局部索引将无法进行分区裁剪,这时会扫描所有分区,增加额外的扫描代价。下述示例语句为查询条件中不指定分区键:
obclient> EXPLAIN SELECT /*+index(t1 idx)*/ b FROM t1 WHERE b=1\G
*************************** 1. row ***************************
Query Plan: ====================================================
|ID|OPERATOR |NAME |EST. ROWS|COST|
----------------------------------------------------
|0 |EXCHANGE IN DISTR | |4950 |3551|
|1 | EXCHANGE OUT DISTR |:EX10000|4950 |3083|
|2 | PX PARTITION ITERATOR| |4950 |3083|
|3 | TABLE SCAN |t1(idx) |4950 |3083|
====================================================
Outputs & filters:
-------------------------------------
0 - output([t1.b]), filter(nil)
1 - output([t1.b]), filter(nil), dop=1
2 - output([t1.b]), filter(nil)
3 - output([t1.b]), filter(nil),
access([t1.b]), partitions(p[0-4])
1 row in set (0.01 sec)