---
title: "创建索引 - OceanBase 数据库 V4.6.0 | OceanBase 文档中心"
description: 创建索引 本文介绍了如何创建索引。 背景信息 OceanBase 数据库支持在非分区表和分区表上创建索引，索引可以是局部索引或全局索引，也可以是唯一索引或非唯一索引，还可以是空间索引或函数索引。如果是分区表的唯一索引，则局部的唯一索引必须包含表分区的分区键。关于索引的更多介绍，请参见 索引简介 章节。 本节主要介绍如…
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库分布式版 - V 4.6.0

# 创建索引

更新时间：2026-05-19 09:54:06

[编辑](https://github.com/oceanbase/oceanbase-doc/edit/V4.6.0/zh-CN/700.reference/300.database-object-management/100.manage-object-of-mysql-mode/500.manage-indexes-of-mysql-mode/200.create-an-index-of-mysql-mode.md)  

本文介绍了如何创建索引。

## 背景信息

OceanBase 数据库支持在非分区表和分区表上创建索引，索引可以是局部索引或全局索引，也可以是唯一索引或非唯一索引，还可以是空间索引或函数索引。如果是分区表的唯一索引，则局部的唯一索引必须包含表分区的分区键。关于索引的更多介绍，请参见 [索引简介](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005685977) 章节。

本节主要介绍如何在非分区表上创建索引，分区表上索引的创建请参见 [在分区表上建立索引](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005685875) 章节。

## 注意事项

创建索引时需要注意，在 OceanBase 数据库中，索引名称在数据库（DataBase）范围内不能重复。

## 创建普通索引

可以使用 `CREATE TABLE` 语句、`CREATE INDEX` 语句或 `ALTER TABLE` 语句来创建普通索引。

### 使用 `CREATE TABLE` 语句创建普通索引

可以通过 `CREATE TABLE` 语句在创建表时即为表创建索引。

语法如下：

```sql
CREATE TABLE table_name(column_name column_definition,[column_name column_definition,...] [UNIQUE] INDEX|KEY [index_name](column_name));

```

相关参数说明如下：

- `table_name`：指定待创建的表的表名。
 - `column_name`：指定表的列。
 - `column_definition`：定义表中各列对应的数据类型。
 - `UNIQUE`：可选，表示唯一索引。创建唯一索引时需要添加该关键字。
 - `INDEX|KEY`：表示在该语句中，索引关键字使用 `INDEX` 或 `KEY` 都可以。
 - `index_name`：可选，指定待创建的索引的索引名。如果未指定，默认索引名与指定的列名相同。

创建表 `tbl1`，同时创建索引 `tbl1_idx1` 的示例如下：

```sql
CREATE TABLE tbl1(id INT,name VARCHAR(18),date DATE,PRIMARY KEY (id),INDEX tbl1_idx1 (date));

```

### 使用 `CREATE INDEX` 语句创建普通索引

可以通过 `CREATE INDEX` 语句为已有的表创建索引。

语法如下：

```sql
CREATE [UNIQUE] INDEX index_name ON table_name (column_name);

```

相关参数说明如下：

- `UNIQUE`：可选，表示唯一索引。创建唯一索引时需要添加该关键字。
 - `index_name`：指定待添加的索引的索引名。
 - `table_name` ：指定待创建索引的表的表名。
 - `column_name` ：指定对哪些列进行索引，指定多列时，各列之间用英文逗号分隔。

创建 `tbl2` 表后，再创建索引 `tbl2_idx1` 的示例如下：

1. 创建表 `tbl2`。

   ```sql
   CREATE TABLE tbl2(id INT,name VARCHAR(20));

   ```
 2. 在表 `tbl2` 上创建索引 `tbl2_idx1`。

   ```sql
   CREATE INDEX tbl2_idx1 ON tbl2(id);

   ```

### 使用 `ALTER TABLE` 语句创建普通索引

可以通过 `ALTER TABLE` 语句为已存在的表创建索引，且该语句支持一次增加多个索引。

语法如下：

```sql
ALTER TABLE table_name ADD [UNIQUE] INDEX|KEY [index_name](column_name);

```

相关参数说明如下：

- `table_name` ：指定待创建索引的表的表名。
 - `UNIQUE`：可选，表示唯一索引。创建唯一索引时需要添加该关键字。
 - `INDEX|KEY`：表示在该语句中，索引关键字使用 `INDEX` 或 `KEY` 都可以。
 - `index_name`：可选，指定待创建的索引的索引名。如果未指定，默认索引名与指定的列名相同。
 - `column_name` ：指定对哪些列进行索引，指定多列时，各列之间用英文逗号分隔。

创建表 `tbl3` 后，在创建索引 `tbl3_idx1` 的示例如下：

1. 创建表 `tbl3`。

   ```sql
   CREATE TABLE tbl3(id INT,name VARCHAR(20));

   ```
 2. 为表 `tbl3` 创建索引 `tbl3_idx1`。

   ```sql
   ALTER TABLE tbl3 ADD INDEX tbl3_idx1(id);

   ```

## 创建空间索引

OceanBase 数据库的 MySQL 模式支持创建空间索引。空间索引是对存储在介质上的数据位置信息的描述，可以用来提高系统对数据获取的效率。

创建空间索引的语法与创建普通索引的语法基本一致，也是使用 `CREATE TABLE` 语句、`CREATE INDEX` 语句或 `ALTER TABLE` 语句来创建索引。不同的是，空间索引需要使用 `SPATIAL` 关键字，并且空间索引中的列必须为 `NOT NULL`。

### 空间索引使用限制

在创建空间索引前，需要了解以下使用限制：

- 空间索引仅支持局部索引，不支持全局索引。
 - 创建空间索引的列必须定义为 `SRID` 属性，否则，在该列上添加的空间索引在后续查询时会无法生效。这是因为，创建空间索引后，在使用空间索引进行比较时，需要使用列定义中的 `SRID` 所对应的坐标系。空间索引存储了几何对象的 MBR（Minimum Bounding Rectangle）构建，而 MBR 的比较方式也依赖于 `SRID`。

  关于 SRID 相关的介绍，请参见 [空间参考系统（SRS）](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005688093)。
 - 只能对空间数据类型的数据列创建空间索引。OceanBase 数据库支持的空间数据类型请参见 [空间数据类型概述](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005688092)。
 - 创建空间索引的列的列属性必须为 `NOT NULL`。

  如果不为 `NOT NULL`，您也可以通过 `ALTER TABLE` 语句先将该列的列属性修改为 `NOT NULL` 后再添加空间索引。修改列属性的具体操作可参见 [定义列的约束类型](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005683179)。

### 使用 `CREATE TABLE` 语句创建空间索引

语法如下：

```sql
CREATE TABLE table_name(column_g_name GEOMETRY NOT NULL SRID 4326,[column_name column_definition,...] SPATIAL INDEX|KEY [index_name](column_g_name));

```

相关参数说明如下：

- `table_name`：指定待创建的表的表名。
 - `column_g_name`、`column_name`：定义表的列名。
 - `SRID 4326`：显示指定空间列的 `SRID`。
 - `column_definition`：定义表中各列对应的数据类型。待添加空间索引的列的列类型必须为空间数据类型。OceanBase 数据库支持的空间数据类型请参见 [空间数据类型概述](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005688092)。
 - `INDEX|KEY`：表示在该语句中，索引关键字使用 `INDEX` 或 `KEY` 都可以。
 - `index_name`：指定待添加的索引的索引名。如果未指定，默认索引名与指定的列名相同。

创建 `tbl1_g` 表，同时添加空间索引 `tbl1_g_idx1` 的示例如下：

```sql
CREATE TABLE tbl1_g (id INT,name VARCHAR(18),g GEOMETRY NOT NULL SRID 4326,SPATIAL INDEX tbl1_g_idx1(g));

```

创建后，可以通过 `SHOW INDEX` 语句查看索引信息。

```sql
SHOW INDEX FROM tbl1_g;

```

查询结果如下：

```shell
+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
| Table  | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment   | Index_comment | Visible |
+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
| tbl1_g |          1 | tbl1_g_idx1 |            1 | g           | A         |        NULL | NULL     | NULL   |      | SPATIAL    | available |               | YES     |
+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
1 row in set

```

### 使用 `CREATE INDEX` 语句创建空间索引

语法如下：

```sql
CREATE SPATIAL INDEX index_name ON table_name(column_g_name);

```

相关参数说明如下：

- `table_name`：指定待创建索引的表的表名。
 - `index_name`：指定待添加的索引的索引名。
 - `column_g_name`：指定对哪些列进行索引，指定多列时，各列之间用英文逗号分隔。待添加空间索引的列的列类型必须为空间数据类型。OceanBase 数据库支持的空间数据类型请参见 [空间数据类型概述](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005688092)。

创建 `tbl2_g` 表后，再创建空间索引 `tbl2_g_idx1` 的示例如下：

1. 创建表 `tbl2_g`。

   ```sql
   CREATE TABLE tbl2_g(id INT,name VARCHAR(20),g GEOMETRY NOT NULL SRID 4326);

   ```
 2. 为表创建空间索引 `tbl2_g_idx1`。

   ```sql
   CREATE SPATIAL INDEX tbl2_g_idx1 ON tbl2_g(g);

   ```
 3. 创建成功后，查看索引信息。

   ```sql
   SHOW INDEX FROM tbl2_g;

   ```

   查询结果如下：

   ```shell
   +--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
   | Table  | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment   | Index_comment | Visible |
   +--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
   | tbl2_g |          1 | tbl2_g_idx1 |            1 | g           | A         |        NULL | NULL     | NULL   |      | SPATIAL    | available |               | YES     |
   +--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
   1 row in set

   ```

### 使用 `ALTER TABLE` 语句创建空间索引

```sql
ALTER TABLE table_name ADD SPATIAL INDEX|KEY [index_name](column_g_name);

```

相关参数说明如下：

- `table_name`：指定待创建索引的表的表名。
 - `INDEX|KEY`：表示在该语句中，索引关键字使用 `INDEX` 或 `KEY` 都可以。
 - `index_name`：可选，指定待添加的索引的索引名。如果未指定，默认索引名与指定的列名相同。
 - `column_g_name`：指定对哪些列进行索引，指定多列时，各列之间用英文逗号分隔。待添加空间索引的列的列类型必须为空间数据类型。OceanBase 数据库支持的空间数据类型请参见 [空间数据类型概述](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005688092)。

创建 `tbl3_g` 表后，再创建空间索引 `tbl3_g_idx1` 的示例如下：

1. 创建表 `tbl3_g`。

   ```sql
   CREATE TABLE tbl3_g(id INT,name VARCHAR(20),g GEOMETRY NOT NULL SRID 4326);

   ```
 2. 在表上创建空间索引。

   ```sql
   ALTER TABLE tbl3_g ADD SPATIAL INDEX tbl3_g_idx1(g);

   ```
 3. 查看索引信息。

   ```sql
   SHOW INDEX FROM tbl3_g;

   ```

   查询结果如下：

   ```shell
   +--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
   | Table  | Non_unique | Key_name    | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment   | Index_comment | Visible |
   +--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
   | tbl3_g |          1 | tbl3_g_idx1 |            1 | g           | A         |        NULL | NULL     | NULL   |      | SPATIAL    | available |               | YES     |
   +--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
   1 row in set

   ```

## 创建函数索引

基于表中一列或多列的值进行计算后的结果建立的索引称为函数索引。函数索引是一种优化技术，使用函数索引可以在查询时快速定位匹配的函数值，从而避免重复计算，提高查询效率。

假设您有一张表 `sale`，表中有一个数据类型为 `date` 的列 `date_col`：

```sql
CREATE TABLE sale(date_col date, sales_col int, name_col varchar(10));

```

如果您需要获取 3 月份的数据，则可以使用 `Month()` 函数来查询数据：

```sql
SELECT * FROM sale WHERE month(date_col) = 3;

```

该场景下，数据库需要为表中的每行计算 `month(date_col)`，并过滤掉不符合 `month(date_col) = 3` 的行。如果您需要频繁地使用月份信息来过滤数据，则每次都需要重新计算 `month(date_col)`，就会造成大量的开销。因此，您可以在 `date_col` 上创建一个函数索引，将 `month(date_col)` 存储到索引表中，来加速查询。

```sql
CREATE INDEX idx1 ON sale((month(date_col)));

```

您可以使用 `CREATE TABLE` 语句、`CREATE INDEX` 语句或 `ALTER TABLE` 语句来创建函数索引。函数索引也可以是唯一索引或空间索引。

### 函数索引使用限制

在 OceanBase 数据库的 MySQL 模式中，对函数索引的表达式进行了限制，禁止部分系统函数的表达式作为函数索引，具体的函数列表请参见 [函数索引支持的系统函数列表](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005683145) 和 [函数索引不支持的系统函数列表](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005683144)。

### 使用 `CREATE TABLE` 语句创建函数索引

可以在创建表时即为表创建函数索引。语法如下：

```sql
CREATE TABLE table_name({column_name column_definition,[column_name column_definition,...]} [UNIQUE| SPATIAL] {INDEX|KEY} [index_name](expr));

```

相关参数说明如下：

- `table_name`：指定待创建索引的表的表名。
 - `column_definition`：定义表中各列的数据类型。
 - `[UNIQUE | SPATIAL]`：可选，`UNIQUE` 表示唯一索引；`SPATIAL` 表示空间索引。创建唯一索引或空间索引时需要添加对应的关键字。
 - `INDEX|KEY`：表示在该语句中，索引关键字使用 `INDEX` 或 `KEY` 都可以。
 - `index_name`：可选，待创建的函数索引的名称。如果不指定，则系统会自动生成一个名称。格式为 `functional_index_xx`，`xx` 为索引编号。
 - `expr`：合法的函数索引表达式，且允许是布尔表达式，例如 `c1=c1`。

创建函数索引 `tbl1_func_idx1` 的示例如下：

```sql
CREATE TABLE tbl1_func (c1 int, c2 int, index tbl1_func_idx1 ((c1+1)), UNIQUE KEY ((c1+c2)));

```

创建成功后，可以通过 `SHOW CREATE TABLE` 语句查看建表语句，语句如下：

```sql
SHOW CREATE TABLE tbl1_func;

```

查询结果如下：

```sql
+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                                                                                                                                                                                                                                                        |
+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tbl1_func | CREATE TABLE `tbl1_func` (
  `c1` int(11) DEFAULT NULL,
  `c2` int(11) DEFAULT NULL,
  UNIQUE KEY `functional_index` ((`c1` + `c2`)) BLOCK_SIZE 16384 LOCAL,
  KEY `tbl1_func_idx1` ((`c1` + 1)) BLOCK_SIZE 16384 LOCAL
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 |
+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set

```

### 使用 `CREATE INDEX` 语句创建函数索引

表创建成功后，可以为已有表创建函数索引。语法如下：

```sql
CREATE [UNIQUE | SPATIAL] INDEX index_name ON table_name (expr);

```

相关参数说明如下：

- `[UNIQUE | SPATIAL]`：可选，`UNIQUE` 表示唯一索引；`SPATIAL` 表示空间索引。创建唯一索引或空间索引时需要添加对应的关键字。
 - `index_name`：待创建的函数索引的名称。
 - `table_name`：待创建索引的表。
 - `expr`：合法的函数索引表达式，且允许是布尔表达式，例如 `c1=c1`。

在表上创建一个索引定义为 `c1+c2 < 1` 的函数索引 `tbl2_func_idx1`，示例如下：

1. 创建表 `tbl2_func`。

   ```sql
   CREATE TABLE tbl2_func(c1 int, c2 int);

   ```
 2. 创建函数索引 `tbl2_func_idx1`。

   ```sql
   CREATE INDEX tbl2_func_idx1 on tbl2_func ((c1+c2 < 1));

   ```
 3. 创建成功后，可以查看创建的函数索引。

   ```sql
   SHOW INDEX FROM tbl2_func;

   ```

   结果如下：

   ```shell
   +-----------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+---------------------+
   | Table     | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment   | Index_comment | Visible | Expression          |
   +-----------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+---------------------+
   | tbl2_func |          1 | tbl2_func_idx1 |            1 | SYS_NC18$   | A         |        NULL | NULL     | NULL   | YES  | BTREE      | available |               | YES     | ((`c1` + `c2`) < 1) |
   +-----------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+---------------------+
   1 row in set

   ```

### 使用 `ALTER TABLE` 语句创建函数索引

语法如下：

```sql
ALTER TABLE table_name ADD [UNIQUE | SPATIAL] {INDEX | KEY} [index_name](expr);

```

相关参数说明如下：

- `table_name`：待创建索引的表。
 - `[UNIQUE | SPATIAL]`：可选，`UNIQUE` 表示唯一索引；`SPATIAL` 表示空间索引。创建唯一索引或空间索引时需要添加对应的关键字。
 - `INDEX|KEY`：表示在该语句中，索引关键字使用 `INDEX` 或 `KEY` 都可以。
 - `index_name`：可选，待创建的函数索引的名称。如果不指定，则系统会自动生成一个名称，且名称格式为 `functional_index` 前缀加编号。
 - `expr`：合法的函数索引表达式，且允许是布尔表达式，例如 `c1=c1`。

1. 创建表 `tbl3_func`。

   ```sql
   CREATE TABLE tbl3_func(c1 int, c2 int);

   ```
 2. 为表创建 2 个函数索引。

   ```sql
   ALTER TABLE tbl3_func ADD INDEX ((c1+1));

   ```

   ```sql
   ALTER TABLE tbl3_func ADD INDEX ((concat(c1,'a')));

   ```sql
   SHOW INDEX FROM tbl3_func;

   ```

   查询结果如下：

   ```shell
   +-----------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------------+
   | Table     | Non_unique | Key_name           | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment   | Index_comment | Visible | Expression       |
   +-----------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------------+
   | tbl3_func |          1 | functional_index   |            1 | SYS_NC18$   | A         |        NULL | NULL     | NULL   | YES  | BTREE      | available |               | YES     | (`c1` + 1)       |
   | tbl3_func |          1 | functional_index_2 |            1 | SYS_NC19$   | A         |        NULL | NULL     | NULL   | YES  | BTREE      | available |               | YES     | concat(`c1`,'a') |
   +-----------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------------+
   2 rows in set

   ```

## 创建列存索引

可以使用 `CREATE TABLE` 语句、`CREATE INDEX` 语句或 `ALTER TABLE` 语句来创建列存索引。

### 使用 CREATE TABLE 语句创建列存索引

可以通过 `CREATE TABLE` 语句在创建表时即为表创建列存索引。

语法如下：

```sql
CREATE TABLE table_name(column_name column_definition,[column_name column_definition,...] [UNIQUE] INDEX|KEY [index_name](column_name) [STORING(column_name, ...)] WITH COLUMN GROUP([all columns, ]each column));

```

相关参数说明如下：

- `table_name`：指定待创建的表的表名。
 - `column_name`：指定表的列。
 - `column_definition`：定义表中各列对应的数据类型。
 - `UNIQUE`：可选，表示唯一索引。创建唯一索引时需要添加该关键字。
 - `INDEX|KEY`：表示在该语句中，索引关键字使用 `INDEX` 或 `KEY` 都可以。
 - `index_name`：可选，指定待创建的索引的索引名。如果未指定，默认索引名与指定的列名相同。
 - `STORING(column_name, ...)`：可选，指定索引表上的冗余列。即使 `column_name` 列不是索引字段，也会按照列存格式进行冗余存储。
 - `WITH COLUMN GROUP([all columns, ]each column)`：指定索引的列存属性。

     - `WITH COLUMN GROUP(all columns, each column)`：指定创建行存列存冗余的索引。
     - `WITH COLUMN GROUP(all columns)`：指定创建行存索引。
     - `WITH COLUMN GROUP(each column)`：指定创建列存索引。

**示例如下：**

- 创建表 `tbl4`，同时创建行存列存冗余索引 `idx1_tbl4_cg`。

  ```sql
  CREATE TABLE tbl4(id INT, name VARCHAR(18), date DATE, PRIMARY KEY (id), INDEX idx1_tbl4_cg (date) WITH COLUMN GROUP(all columns, each column));

  ```
 - 创建表 `tbl5`，同时创建列存索引 `idx1_tbl5_cg`，并且在索引表上存储 `id` 列的冗余数据。

  ```sql
  CREATE TABLE tbl5(id INT, name VARCHAR(18), date DATE, INDEX idx1_tbl5_cg (date) STORING(id) WITH COLUMN GROUP(each column));

  ```

### 使用 CREATE INDEX 语句创建列存索引

可以通过 `CREATE INDEX` 语句为已有的表创建列存索引。

语法如下：

```sql
CREATE [UNIQUE] INDEX index_name ON table_name (column_name) [STORING(column_name, ...)] WITH COLUMN GROUP([all columns, ]each column);

```

相关参数说明如下：

- `UNIQUE`：可选，表示唯一索引。创建唯一索引时需要添加该关键字。
 - `index_name`：指定待添加的索引的索引名。
 - `table_name` ：指定待创建索引的表的表名。
 - `column_name` ：指定对哪些列进行索引，指定多列时，各列之间用英文逗号分隔。
 - `STORING(column_name, ...)`：可选，指定索引表上的冗余列。即使 `column_name` 列不是索引字段，也会按照列存格式进行冗余存储。
 - `WITH COLUMN GROUP([all columns, ]each column)`：指定索引的列存属性。

**示例如下：**

创建 `tbl6` 表后，再创建列存索引 `idx1_tbl6_cg`。

1. 创建表 `tbl6`。

   ```sql
   CREATE TABLE tbl6(id INT, name VARCHAR(20), age INT);

   ```
 2. 在表 `tbl6` 上创建列存索引 `idx1_tbl6_cg`，并且在索引表上存储 `age` 列的冗余数据。

   ```sql
   CREATE INDEX idx1_tbl6_cg ON tbl6(id) STORING(age) WITH COLUMN GROUP(each column);

   ```

### 使用 ALTER TABLE 语句创建列存索引

可以通过 `ALTER TABLE` 语句为已存在的表创建列存索引。

语法如下：

```sql
ALTER TABLE table_name ADD [UNIQUE] INDEX|KEY [index_name](column_name) [STORING(column_name, ...)] WITH COLUMN GROUP([all columns, ]each column);

```

相关参数说明如下：

- `table_name` ：指定待创建索引的表的表名。
 - `UNIQUE`：可选，表示唯一索引。创建唯一索引时需要添加该关键字。
 - `INDEX|KEY`：表示在该语句中，索引关键字使用 `INDEX` 或 `KEY` 都可以。
 - `index_name`：可选，指定待创建的索引的索引名。如果未指定，默认索引名与指定的列名相同。
 - `column_name` ：指定对哪些列进行索引，指定多列时，各列之间用英文逗号分隔。
 - `STORING(column_name, ...)`：可选，指定索引表上的冗余列。即使 `column_name` 列不是索引字段，也会按照列存格式进行冗余存储。
 - `WITH COLUMN GROUP([all columns, ]each column)`：指定索引的列存属性。

**示例如下：**

创建表 `tbl7` 后，在创建列存索引 `idx1_tbl6_cg`。

1. 创建表 `tbl7`。

   ```sql
   CREATE TABLE tbl7(id INT, name VARCHAR(20), age INT);

   ```
 2. 为表 `tbl7` 创建列存索引 `idx1_tbl7_cg`，并且在索引表上存储 `age` 列的冗余数据。

   ```sql
   ALTER TABLE tbl7 ADD INDEX idx1_tbl7_cg(id) STORING(age) WITH COLUMN GROUP(each column);

   ```

## 创建多值索引

在 OceanBase 数据库支持在创建表时（`CREATE TABLE`）来预先创建多值索引。目前不支持在表创建之后添加多值索引，但可以通过 `ALTER TABLE` 语句来删除已存在的索引。对于已创建包含多值索引的主表，支持了复杂 DML 操作。

### 多值索引的使用限制

- 每个多值索引只允许有一个多值键部分。然而，`CAST(... AS ... ARRAY)` 表达式可以引用 JSON 文档中的多个数组，如下所示：

  ```sql
  CAST(data->'$.arr[*][*]' AS UNSIGNED ARRAY)

  ```

  在这种情况下，所有匹配 JSON 表达式的值都作为单个平面数组存储在索引中。
 - 多值索引不能是覆盖索引。
 - 在多值键部分中允许的唯一类型的表达式是 JSON 表达式。表达式不必引用插入到索引列中的 JSON 文档中的现有元素，但必须在语法上有效。
 - 由于同一个聚簇索引记录的索引记录在多值索引中分散，多值索引不支持范围扫描或仅索引扫描。
 - 多值索引不允许在外键规范中使用。
 - 不能为多值索引定义索引前缀。
 - 不能在 Binary 类型的数据上定义多值索引。
 - 多值索引对 Offline DDL 的支持情况请见[Offline DDL](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005686194)。

### 使用 CREATE TABLE 语句创建多值索引

**使用 `CREATE TABLE` 语句创建多值索引简化语法如下：**

创建多值索引：

```sql
CREATE TABLE table_name(column_name column_definition, [column_name column_definition, ...],
    json_column_name JSON,
    [UNIQUE] INDEX idx_json_name((CAST(json_column_name->'$.json_field_name' AS UNSIGNED ARRAY)))
);

```

创建复合多值索引：

```sql
CREATE TABLE table_name(column_name column_definition, [column_name column_definition, ...],
    json_column_name JSON,
    INDEX idx_json_name(column_name, [column_name, ...] (CAST(json_column_name->'$.json_field_name' AS CHAR(n) ARRAY)))
);

```

相关参数说明如下：

- `table_name`：指定待创建的表的表名。
 - `column_name`：指定表其他（除 `JSON` 外）数据类型的列名称。
 - `column_definition`：定义表中各列对应的数据类型。
 - `json_column_name`：指定表 `JSON` 数据类型的列名称。
 - `UNIQUE`：可选，表示创建唯一多值索引。唯一多值索引，索引 Key 不可以重复。

  #### 注意

  多值索引可以定义为唯一索引。如果将其定义为唯一索引，尝试插入已存在于多值索引中的值会返回重复键错误。如果已经存在重复值，尝试添加唯一的多值索引会失败。
 - `idx_json_name` ：指定待创建的多值索引的索引名。
 - `json_field_name`：Json 列中需要创建索引的字段名称。

更多创建表语法信息，参见 [CREATE TABLE](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005686098)。

**创建多值示例如下：**

1. 创建表 `json_tbl1`，同时创建多值索引 `idx1_json_tbl1`。

   ```sql
   CREATE TABLE json_tbl1(col1 INT, col2 VARCHAR(18), col3 JSON,
      INDEX idx1_json_tbl1((CAST(col3->'$.ipcode' AS UNSIGNED ARRAY)))
   );

   ```
 2. 使用以下语句向表 `json_tbl1` 中插入测试数据。

   ```sql
   INSERT INTO json_tbl1 VALUES(1, 'a1', '{"user":"Jk001","user_id":37,"ipcode":[94582,94536]}'),
      (2, 'a2', '{"user":"Jk002","user_id":22,"ipcode":[94568,94507,94582]}'),
      (3, 'a3', '{"user":"Jk003","user_id":31,"ipcode":[94477,94507]}'),
      (4, 'a4', '{"user":"Jk004","user_id":72,"ipcode":[94536]}'),
      (5, 'a5', '{"user":"Jk005","user_id":56,"ipcode":[94507,94582]}');

   ```

创建表 `json_tbl2`，同时创建复合多值索引 `idx1_json_tbl2`。

```sql
CREATE TABLE json_tbl2(col1 INT, col2 VARCHAR(18), col3 JSON,
      INDEX idx1_json_tbl2(col1, (CAST(col3->'$.ipcode' AS UNSIGNED ARRAY)))
);

```

### 支持复杂 DML

对于已创建包含多值索引的主表，支持复杂 DML 操作，示例如下：

- `INSERT INTO ON DUPLICATE KEY`

  ```sql
  CREATE TABLE customers(id INT PRIMARY KEY, uid INT, j JSON);

  INSERT INTO customers VALUES (10, 21, '{"user":"Jack","user_id":37,"zipcode":[94582,94536]}');

  CREATE INDEX zips ON customers((CAST(j->'$.zipcode' AS UNSIGNED ARRAY)));

  INSERT INTO customers
  VALUES (10, 22, '{"user":"Jack","user_id":37,"zipcode":[24582,34536]}')
  ON DUPLICATE KEY
  UPDATE j = '{"user":"Jack","user_id":37,"zipcode":[34582,44536]}';

  ```
 - `REPLACE INTO`

  ```sql
  CREATE TABLE test_array(id int,a varchar(50),j json,INDEX index_1( (CAST(j->'$.key' AS UNSIGNED ARRAY))) );

  INSERT INTO test_array VALUES(1,'test','{"key":[1,2,3,4]}');

  REPLACE INTO test_array VALUES(1,'test','{"key":[8,9,13,43]}');

  ```
 - 多表的 `UPDATE` 和 `DELETE`

  示例表准备如下：

  ```sql
  CREATE TABLE table_1(a int PRIMARY KEY, b json, INDEX index_1( (CAST(b->'$.key' AS UNSIGNED ARRAY))) );
  CREATE TABLE table_2(a int PRIMARY KEY, b json);

  INSERT INTO table_1 values(1, '{"key":[1,2,3,4]}');
  INSERT INTO table_2 values(1, '{"key":[1,2,3,4]}');

  ```

  `UPDATE` 示例如下：

  ```sql
  UPDATE table_1 JOIN table_2 ON table_1.a = table_2.a
  SET table_1.b = '{"key":[11,12,13,14]}', table_2.b = '{"key":[21,22,23,24]}';

  UPDATE  table_1 JOIN table_2 ON table_1.a = table_2.a SET table_1.b = '{"key":[31,32,33,34]}';
  UPDATE table_1 JOIN table_2 ON table_1.a = table_2.a SET table_2.b = table_1.b;

  ```

  `DELETE` 示例如下：

  ```sql
  DELETE table_1, table_2 FROM table_1 JOIN table_2 ON table_1.a = table_2.a;
  DELETE table_1 FROM table_1 JOIN table_2 ON table_1.a = table_2.a;
  DELETE table_1 FROM table_1 JOIN table_2 ON table_1.a = table_2.a;

  ```
 - 可更新视图

  ```sql
  CREATE TABLE test(id int,a varchar(50),j json,INDEX index_1( (CAST(j->'$.key' AS UNSIGNED ARRAY))) );

  INSERT INTO test values(1,'test','{"key":[1,2,3,4]}');

  CREATE VIEW vtest AS SELECT * FROM test;

  UPDATE vtest SET j='{"key":[1,2]}';

  ```

### 后建多值索引

后建多值索引需要首先开启配置项 `_enable_add_fulltext_index_to_existing_table`。

```sql
ALTER SYSTEM SET _enable_add_fulltext_index_to_existing_table = true;

```

后建多值索引分类如下：

| 分类 | 描述 |
| --- | --- |
| 多值索引 | 使用 `ADD INDEX/ALTER TABLE` 创建多值索引 |
| 复合多值索引 | 使用 `ADD INDEX/ALTER TABLE` 创建非唯一复合多值索引,复合多值索引:只允许一列是多值索引，其他列是普通列 |
| 唯一多值索引 | 使用 `ADD INDEX/ALTER TABLE` 创建唯一多值索引 |
| 唯一复合多值索引 | 使用 `ADD INDEX/ALTER TABLE` 创建唯一复合多值索引,复合多值索引:只允许一列是多值索引，其他列是普通列 |

示例分别如下：

1. 创建表 `json_tbl1`，同时创建（非唯一）多值索引 `idx1_json_tbl1`。

   ```sql
   CREATE TABLE json_tbl1(id INT PRIMARY KEY, uid INT, j JSON);

   INSERT INTO json_tbl1 VALUES
   (10, 21, '{"user":"Jack","user_id":37,"zipcode":[94582,94536]}'),
   (11, 22, '{"user":"Jill","user_id":22,"zipcode":[94568,94507,94582]}'),
   (12, 23, '{"user":"Bob","user_id":31,"zipcode":[94477,94507]}'),
   (13, 24, '{"user":"Mary","user_id":72,"zipcode":[94536]}'),
   (14, 25, '{"user":"Ted","user_id":56,"zipcode":[94507,94582]}');

   CREATE INDEX idx1_json_tbl1 ON json_tbl1((CAST(j->'$.zipcode' AS UNSIGNED ARRAY)));

   ```
 2. 创建唯一多值索引 `idx1_json_tbl2`。

   ```sql
   CREATE TABLE json_tbl2(id INT PRIMARY KEY, uid INT, j JSON);

   INSERT INTO json_tbl2 VALUES
   (10, 21, '{"user":"Jack","user_id":37,"zipcode":[94507,94536]}'),
   (11, 22, '{"user":"Jill","user_id":22,"zipcode":[94568,94582]}'),
   (12, 23, '{"user":"Bob","user_id":31,"zipcode":[94477]}');

   CREATE UNIQUE INDEX idx1_json_tbl2 ON json_tbl2((CAST(j->'$.zipcode' AS UNSIGNED ARRAY)));

   ```
 3. 创建复合多值索引 `idx1_json_tbl3`。

   ```sql
   CREATE TABLE json_tbl3 (
    id BIGINT NOT NULL PRIMARY KEY,
    c1 BIGINT NOT NULL,
    modified  BIGINT NOT NULL,
    custinfo JSON
   );

   INSERT INTO json_tbl3 VALUES
   (10, 21, 101, '{"user":"Jack","user_id":37,"zipcode":[94582,94536]}'),
   (11, 22, 102, '{"user":"Jill","user_id":22,"zipcode":[94568,94507,94582]}'),
   (12, 23, 103, '{"user":"Bob","user_id":31,"zipcode":[94477,94507]}'),
   (13, 24, 104, '{"user":"Mary","user_id":72,"zipcode":[94536]}'),
   (14, 25, 105, '{"user":"Ted","user_id":56,"zipcode":[94507,94582]}');

   CREATE INDEX idx1_json_tbl3 ON json_tbl3 (c1, modified,
        (CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)) );

   ```
 4. 创建唯一复合多值索引 `idx1_json_tbl4`。

   ```sql
   CREATE TABLE json_tbl4 (
    id BIGINT NOT NULL PRIMARY KEY,
    c1 BIGINT NOT NULL,
    modified  BIGINT NOT NULL,
    custinfo JSON
   );

   INSERT INTO json_tbl4 VALUES
   (10, 21, 101, '{"user":"Jack","user_id":37,"zipcode":[94582,94536]}'),
   (11, 22, 102, '{"user":"Jill","user_id":22,"zipcode":[94568,94507,94582]}'),
   (12, 23, 103, '{"user":"Bob","user_id":31,"zipcode":[94477,94507]}'),
   (13, 24, 104, '{"user":"Mary","user_id":72,"zipcode":[94536]}'),
   (14, 25, 105, '{"user":"Ted","user_id":56,"zipcode":[94507,94582]}');

   CREATE UNIQUE INDEX idx1_json_tbl4 ON json_tbl4 (c1, modified,
        (CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)) );

   ```

### 查询中使用多值索引

优化器在 `WHERE` 子句中指定了以下函数时，会使用多值索引来查询。

- [MEMBER OF()](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005688062)
 - [JSON_CONTAINS()](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005688065)
 - [JSON_OVERLAPS](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005688067)

**示例如下：**

- 使用 `MEMBER OF()` 查询示例。

  ```sql
  SELECT *
     FROM json_tbl1
     WHERE 94507 MEMBER OF(col3->'$.ipcode');

  ```

  返回结果如下：

  ```shell
  +------+------+-------------------------------------------------------------------+
  | col1 | col2 | col3                                                              |
  +------+------+-------------------------------------------------------------------+
  |    2 | a2   | {"user": "Jk002", "ipcode": [94568, 94507, 94582], "user_id": 22} |
  |    3 | a3   | {"user": "Jk003", "ipcode": [94477, 94507], "user_id": 31}        |
  |    5 | a5   | {"user": "Jk005", "ipcode": [94507, 94582], "user_id": 56}        |
  +------+------+-------------------------------------------------------------------+
  3 rows in set

  ```
 - 对表 `json_tbl1` 执行查询，筛选出 `col3` 列中的 JSON 数据中字段 `ipcode` 中包含值 94507 的行。使用 `EXPLAIN` 命令查看查询的执行计划。

  ```sql
  EXPLAIN SELECT *
     FROM json_tbl1
     WHERE 94507 MEMBER OF(col3->'$.ipcode');

  ```

  返回结果如下：

  ```shell
  +-------------------------------------------------------------------------------------------------------------------------------------------------------+
  | Query Plan                                                                                                                                            |
  +-------------------------------------------------------------------------------------------------------------------------------------------------------+
  | =====================================================================                                                                                 |
  | |ID|OPERATOR        |NAME                     |EST.ROWS|EST.TIME(us)|                                                                                 |
  | ---------------------------------------------------------------------                                                                                 |
  | |0 |TABLE RANGE SCAN|json_tbl1(idx1_json_tbl1)|3       |13          |                                                                                 |
  | =====================================================================                                                                                 |
  | Outputs & filters:                                                                                                                                    |
  | -------------------------------------                                                                                                                 |
  |   0 - output([json_tbl1.col1], [json_tbl1.col2], [json_tbl1.col3]), filter(nil)                                                                       |
  |       access([json_tbl1.__pk_increment], [json_tbl1.col3], [json_tbl1.col1], [json_tbl1.col2]), partitions(p0)                                        |
  |       is_index_back=true, is_global_index=false,                                                                                                      |
  |       range_key([json_tbl1.SYS_NC_mvi_19], [json_tbl1.__pk_increment], [json_tbl1.__doc_id_1715756608129539]), range(94507,MIN,MIN ; 94507,MAX,MAX),  |
  |       range_cond([JSON_MEMBER_OF(94507, json_tbl1.SYS_NC_mvi_19)])                                                                                    |
  +-------------------------------------------------------------------------------------------------------------------------------------------------------+
  12 rows in set

  ```
 - 使用 `JSON_CONTAINS()` 查询示例。

  ```sql
  SELECT *
     FROM json_tbl1
     WHERE JSON_CONTAINS(col3->'$.ipcode', CAST('[94507,94582]' AS JSON));

  ```

  返回结果如下：

  ```shell
  +------+------+-------------------------------------------------------------------+
  | col1 | col2 | col3                                                              |
  +------+------+-------------------------------------------------------------------+
  |    2 | a2   | {"user": "Jk002", "ipcode": [94568, 94507, 94582], "user_id": 22} |
  |    5 | a5   | {"user": "Jk005", "ipcode": [94507, 94582], "user_id": 56}        |
  +------+------+-------------------------------------------------------------------+
  2 rows in set

  ```
 - 使用 `JSON_OVERLAPS()` 查询示例。

  ```sql
  SELECT *
     FROM json_tbl1
     WHERE JSON_OVERLAPS(col3->'$.ipcode', CAST('[94507,94582]' AS JSON));

  ```

  返回结果如下：

  ```shell
  +------+------+-------------------------------------------------------------------+
  | col1 | col2 | col3                                                              |
  +------+------+-------------------------------------------------------------------+
  |    1 | a1   | {"user": "Jk001", "ipcode": [94582, 94536], "user_id": 37}        |
  |    2 | a2   | {"user": "Jk002", "ipcode": [94568, 94507, 94582], "user_id": 22} |
  |    3 | a3   | {"user": "Jk003", "ipcode": [94477, 94507], "user_id": 31}        |
  |    5 | a5   | {"user": "Jk005", "ipcode": [94507, 94582], "user_id": 56}        |
  +------+------+-------------------------------------------------------------------+
  4 rows in set

  ```

## 创建全文索引

OceanBase 数据库 MySQL 模式当前版本可以使用 `CREATE TABLE` 语句、`CREATE FULLTEXT INDEX` 语句或 `ALTER TABLE` 语句来创建全文索引。

更多全文索引信息，参见 [全文索引](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005685980)。

使用全文索引查询数据的信息，参见 [全文查询](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005686050)。

### 全文索引使用限制及注意事项

非分区表和分区表上有无主键都可以创建全文索引，创建全文索引限制如下：

- 全文索引仅支持应用于 `CHAR`、`VARCHAR` 和 `TEXT` 类型的列。
 - 当前版本只支持创建局部（`LOCAL`）全文索引。
 - 创建全文索引时不可以指定 `UNIQUE` 关键字。
 - 如果要创建涉及多列的全文索引，则必须确保这些列具有相同的字符集。
 - 全文索引对 Offline DDL 的支持情况请见[Offline DDL](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005686194)。

### 使用 CREATE TABLE 语句创建全文索引

通过 `CREATE TABLE` 语句在创建表时即为表创建全文索引，简化语法如下：

```sql
CREATE TABLE table_name(column_name column_definition,[column_name column_definition,...]
    FULLTEXT [INDEX | KEY] [index_name](column_name)
    [WITH PARSER tokenizer_option]
    [PARSER_PROPERTIES[=](parser_properties_list)]
    [LOCAL]);

tokenizer_option:
    SPACE
    | NGRAM
    | BENG
    | IK
    | NGRAM2

parser_properties_list:
    parser_properties, [parser_properties]

parser_properties:
    min_token_size = int_value
    | max_token_size = int_value
    | ngram_token_size = int_value
    | ik_mode = 'char_value'
    | min_ngram_size = int_value
    | max_ngram_size = int_value

```

更多 `CREATE TABLE` 语法信息，参见 [CREATE TABLE](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005686098)。

**相关参数说明如下：**

- `table_name`：指定待创建的表的表名。
 - `column_name`：指定表的列。
 - `column_definition`：定义表中各列对应的数据类型。
 - `FULLTEXT`：指定创建全文索引。

  #### 注意

  当前版本只支持创建局部全文索引。
 - `INDEX | KEY`：表示在该语句中，索引关键字使用 `INDEX` 或 `KEY` 都可以。
 - `index_name`：可选，指定待创建的索引的索引名。如果未指定，默认索引名与指定的列名相同。
 - `WITH PARSER tokenizer_option`：可选项，指定全文索引的分词器。取值如下：

     - `SPACE`：默认值，表示按空格进行分词。可以指定以下属性：

      | 属性 | 取值范围 |
      | --- | --- |
      | min_token_size | [1, 16] |
      | max_token_size | [10, 84] |
     - `NGRAM`：表示基于 N-Gram（中文）的分词方式。可以指定以下属性：

      | 属性 | 取值范围 |
      | --- | --- |
      | ngram_token_size | [1, 10] |
     - `NGRAM2`：表示将文本拆成 `min_ngram_size`～`max_ngram_size` 范围的连续字符。

      | 属性 | 取值范围 |
      | --- | --- |
      | min_ngram_size | [1, 16] |
      | max_ngram_size | [1, 16] |
     - `BENG`：基于 Beng （基础英文）的分词方式。可以指定以下属性：

      | 属性 | 取值范围 |
      | --- | --- |
      | min_token_size | [1, 16] |
      | max_token_size | [10, 84] |
     - `IK`：表示基于 IK（中文）的分词方式。当前仅支持 `utf-8` 字符集。可以指定以下属性：

      | 属性 | 取值范围 |
      | --- | --- |
      | ik_mode | - `smart`     - `max_word` |

  可以使用 [TOKENIZE](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005687292) 函数查看文本按照指定的分词器及 Json 形式参数的分词结果。
 - `PARSER_PROPERTIES[=](parser_properties_list)`：可选项，指定分词器的属性。取值如下：

     - `min_token_size`：表示最小分词长度，默认值为 3，取值范围是 1 到 16。
     - `max_token_size`：表示最大分词长度，默认值为 84，取值范围是 10 到 84。
     - `ngram_token_size`：表示 `NGRAM` 的分词长度，只有 `NGRAM` 分词器有效，默认值为 2，取值范围是 1 到 10。
     - `ik_mode`: 表示 `IK` 分词器的分词模式。取值如下：

           - `smart`：默认值，表示词典中的词汇会被用来提高分词的准确性，词典中的词汇边界会被优先考虑，从而可能减少不必要的扩展。
           - `max_word`：表示在词典中定义的词汇会被识别出来，但不会影响分词的最大化扩展。即使词典中有定义，`max_word` 模式仍然会尝试将文本切分成更多的词汇。
 - `LOCAL`：可选，指定创建局部索引。

**示例如下：**

- 创建表 `tbl1`，同时创建全文索引 `full_idx1_tbl1`。

  ```sql
  CREATE TABLE tbl1(id INT, name VARCHAR(18), date DATE, PRIMARY KEY (id), FULLTEXT INDEX full_idx1_tbl1(name));

  ```
 - 创建表 `tbl2`，同时创建全文索引 `full_idx1_tbl2`，指定全文索引的分词器为 `NGRAM`，同时通过 `PARSER_PROPERTIES` 设置分词器属性。

  ```sql
  CREATE TABLE tbl2(id INT, name VARCHAR(18), doc TEXT,
      FULLTEXT INDEX full_idx1_tbl2(name, doc)
        WITH PARSER NGRAM
        PARSER_PROPERTIES=(ngram_token_size=3));

  ```

### 使用 CREATE FULLTEXT INDEX 语句创建全文索引

通过 `CREATE FULLTEXT INDEX` 语句为已有的表创建全文索引，语法如下：

```sql
CREATE FULLTEXT INDEX index_name ON table_name (column_name, [column_name ...])
    [WITH PARSER tokenizer_option]
    [PARSER_PROPERTIES[=](parser_properties_list)]
    [LOCAL];

```

更多 `CREATE INDEX` 语法信息，参见 [CREATE INDEX](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005686100)。

- `index_name`：指定待添加的索引的索引名。
 - `table_name` ：指定待创建索引的表的表名。
 - `column_name` ：指定对哪些列进行索引，指定多列时，各列之间用英文逗号分隔。
 - `WITH PARSER tokenizer_option`：可选项，指定全文索引的分词器。取值如下：

      | 属性 | 取值范围 |
      | --- | --- |
      | ngram_token_size | [1, 10] |
     - `NGRAM2`：表示将文本拆成 `min_ngram_size`～`max_ngram_size` 范围的连续字符。可以指定以下属性：

           - `smart`：默认值，表示词典中的词汇会被用来提高分词的准确性，词典中的词汇边界会被优先考虑，从而可能减少不必要的扩展。
           - `max_word`：表示在词典中定义的词汇会被识别出来，但不会影响分词的最大化扩展。即使词典中有定义，`max_word` 模式仍然会尝试将文本切分成更多的词汇。
 - `LOCAL`：可选项，指定创建局部索引。

**示例如下：**

创建 `tbl3` 表后，再创建全文索引 `ft_idx1_tbl3`。

   ```sql
   CREATE TABLE tbl3(col1 INT, col2 VARCHAR(4096));

   ```
 2. 在表 `tbl3` 上创建全文索引 `ft_idx1_tbl3`，指定全文索引的分词器为 `IK`，同时通过 `PARSER_PROPERTIES` 设置分词器属性。

   ```sql
   CREATE FULLTEXT INDEX ft_idx1_tbl3 ON tbl3(col2)
       WITH PARSER IK
       PARSER_PROPERTIES=(ik_mode='max_word');

   ```

### 使用 ALTER TABLE 语句创建全文索引

通过 `ALTER TABLE` 语句为已有的表添加全文索引，语法如下：

```sql
ALTER TABLE table_name ADD FULLTEXT [INDEX | KEY] [index_name](column_name, [column_name ...])
    [WITH PARSER tokenizer_option]
    [PARSER_PROPERTIES[=](parser_properties_list)]
    [LOCAL];

```

更多通过 `ALTER TABLE` 语句为已有的表添加全文索引的语法信息，参见 [ALTER TABLE](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005686147)。

- `table_name` ：指定待创建索引的表的表名。
 - `INDEX | KEY`：可选项，表示在该语句中，索引关键字使用 `INDEX` 或 `KEY` 都可以，缺省值为 `KEY`。
 - `index_name`：可选项，指定待创建的索引的索引名。如果未指定，默认索引名与指定的列名相同。
 - `column_name` ：指定对哪些列进行索引，指定多列时，各列之间用英文逗号分隔。
 - `WITH PARSER tokenizer_option`：可选项，指定全文索引的分词器。取值如下：

**示例如下：**

创建表 `tbl4` 后，然后再添加全文索引 `ft_idx1_tbl4`。

1. 创建表 `tbl4`。

   ```sql
   CREATE TABLE tbl4(col1 INT, col2 TEXT);

   ```
 2. 为表 `tbl4` 添加全文索引 `ft_idx1_tbl4`，指定全文索引的分词器为 `BENG`，同时通过 `PARSER_PROPERTIES` 设置分词器属性。

   ```sql
   ALTER TABLE tbl4 ADD FULLTEXT INDEX ft_idx1_tbl4(col2)
       WITH PARSER BENG
       PARSER_PROPERTIES=(min_token_size=2, max_token_size=64);

   ```

## 创建搜索索引（Search Index）

#### 注意

- `WITH (...)` 仅对 JSON 列生效。
 - `INCLUDE_PATHS` 与 `EXCLUDE_PATHS` 不能同时指定。

### 使用 CREATE SEARCH INDEX 语句创建搜索索引

通过 `CREATE SEARCH INDEX` 语句在已有表上创建搜索索引，语法如下：

```sql
CREATE SEARCH INDEX index_name ON table_name (
    search_index_column
    [, search_index_column ...]
) [LOCAL];

search_index_column:
    column_name [WITH (search_col_option_list)]

search_col_option_list:
    [INCLUDE_PATHS = ('path1'[, 'path2']...)]
    [| EXCLUDE_PATHS = ('path1'[, 'path2']...)]
    [| INCLUDE_TYPES = (type1[, type2]...)]

```

更多使用 `CREATE SEARCH INDEX` 创建搜索索引的语法信息、支持的数据类型等，参见 [CREATE INDEX](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005686100)。

- `index_name`：指定待创建的搜索索引名称。
 - `table_name`：指定待创建索引的表名。
 - `search_index_column`：搜索索引列定义，可指定一个或多个列；每列可通过 `WITH (...)` 指定列级路径与类型选项。
 - `INCLUDE_PATHS / EXCLUDE_PATHS`：列级路径白名单/黑名单，二者二选一，用于控制该列参与索引构建的 JSON 路径。
 - `INCLUDE_TYPES`：列级类型过滤，仅索引指定 JSON 标量类型（当前支持 `JSON_STRING`、`JSON_NUMBER`）。
 - `LOCAL`：可选项，用于在分区表上创建局部搜索索引。当前分区表仅支持局部搜索索引。

**示例如下：**

创建表 `tbl_search_1` 后，再创建搜索索引 `search_idx_1`。

1. 创建表 `tbl_search_1`。

   ```sql
   CREATE TABLE tbl_search_1 (
     id INT,
     doc JSON,
     c2 VARCHAR(64)
   ) ORGANIZATION = HEAP;

   ```
 2. 在表 `tbl_search_1` 上创建搜索索引 `search_idx_1`，并为 JSON 列配置路径白名单与类型过滤。

   ```sql
   CREATE SEARCH INDEX search_idx_1 ON tbl_search_1(
     doc WITH (
       INCLUDE_PATHS = ('$.name', '$.score'),
       INCLUDE_TYPES = (JSON_STRING, JSON_NUMBER)
     ),
     c2
   );

   ```

### 使用 CREATE TABLE 语句创建搜索索引

通过 `CREATE TABLE` 语句在创建表时同时创建搜索索引，语法如下：

```sql
CREATE TABLE table_name (
    ...,
    SEARCH INDEX index_name (
        search_index_column
        [, search_index_column ...]
    )
) ORGANIZATION = HEAP;

```

更多使用 `CREATE TABLE` 创建搜索索引的语法信息、支持的数据类型等，参见 [CREATE TABLE](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005686098)。

- `table_name`：指定待创建索引的表名。
 - `index_name`：指定待创建的搜索索引名称。
 - `search_index_column`：搜索索引列定义，可指定一个或多个列；每列可通过 `WITH (...)` 指定列级路径与类型选项。

**示例如下：**

创建表 `tbl_search_3` 时，同时创建搜索索引 `search_idx_3`。

```sql
CREATE TABLE tbl_search_3 (
  id INT,
  profile JSON,
  tag VARCHAR(32),
  SEARCH INDEX search_idx_3 (
    profile WITH (EXCLUDE_PATHS = ('$.debug')),
    tag
  )
) ORGANIZATION = HEAP;

```

### 使用 ALTER TABLE 语句创建搜索索引

通过 `ALTER TABLE` 语句为已有表添加搜索索引，语法如下：

```sql
ALTER TABLE table_name
ADD SEARCH INDEX [index_name] (
    search_index_column
    [, search_index_column ...]
);

```

更多通过 `ALTER TABLE` 语句为已有的表添加搜索索引的语法信息，参见 [ALTER TABLE](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005686147)。

- `table_name`：指定待添加搜索索引的表名。
 - `index_name`：可选项，指定搜索索引名称；若未指定，系统将按规则生成默认索引名。
 - `search_index_column`：搜索索引列定义，可指定一个或多个列；每列可通过 `WITH (...)` 指定列级路径与类型选项。
 - `INCLUDE_PATHS / EXCLUDE_PATHS`：列级路径白名单/黑名单，二者二选一，用于控制该列参与索引构建的 JSON 路径。
 - `INCLUDE_TYPES`：列级类型过滤，仅索引指定 JSON 标量类型（当前支持 `JSON_STRING`、`JSON_NUMBER`）。

**示例如下：**

创建表 `tbl_search_2` 后，再通过 `ALTER TABLE` 添加搜索索引 `search_idx_2`。

1. 创建表 `tbl_search_2`。

   ```sql
   CREATE TABLE tbl_search_2 (
     id INT,
     profile JSON,
     tag VARCHAR(32)
   ) ORGANIZATION = HEAP;

   ```
 2. 为表 `tbl_search_2` 添加搜索索引 `search_idx_2`。

   ```sql
   ALTER TABLE tbl_search_2
   ADD SEARCH INDEX search_idx_2 (
     profile WITH (EXCLUDE_PATHS = ('$.debug')),
     tag
   );

   ```

## 相关文档

更多 MySQL 模式下索引相关的内容，参见以下信息：

- [索引简介](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005685977)
 - [在分区表上建立索引](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005685875)
 - [查看索引](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005683143)
 - [删除索引](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000005683147)

 上一篇 下一篇 ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
