局部索引 
=========================



局部索引又名分区索引，创建索引的分区关键字是 LOCAL。局部索引的分区键等同于表的分区键，局部索引的分区数等同于表的分区数，所以局部索引的分区机制和表的分区机制一样。

下述示例语句为给分区表 t1 创建一个局部索引 idx：

```sql
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：

```sql
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 中，局部索引同样支持分区裁剪。使用分区裁剪的前提条件是查询条件中能够指定分区键，可以减少在查询过程中读取的分区个数，从而能够提高查询检索的效率。下述示例语句为查询条件中指定分区键：

```sql
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)
```



如果在查询中，没有指定分区键，那么局部索引将无法进行分区裁剪，这时会扫描所有分区，增加额外的扫描代价。下述示例语句为查询条件中不指定分区键：

```sql
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)
```


