首批通过分布式安全可靠测评,为关键业务系统打造
创建索引
更新时间:2026-02-22 10:57:51
本文介绍了如何创建索引。
背景信息
OceanBase 数据库支持在非分区表和分区表上创建索引,索引可以是局部索引或全局索引,也可以是唯一索引或非唯一索引,还可以是空间索引或函数索引。如果是分区表的唯一索引,则局部的唯一索引必须包含表分区的分区键。关于索引的更多介绍,请参见 索引简介 章节。
本节主要介绍如何在非分区表上创建索引,分区表上索引的创建请参见 在分区表上建立索引 章节。
注意事项
创建索引时需要注意,在 OceanBase 数据库中,索引名称在数据库(DataBase)范围内不能重复。
创建普通索引
可以使用 CREATE TABLE 语句、CREATE INDEX 语句或 ALTER TABLE 语句来创建普通索引。
使用 CREATE TABLE 语句创建普通索引
可以通过 CREATE TABLE 语句在创建表时即为表创建索引。
语法如下:
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 的示例如下:
CREATE TABLE tbl1(id INT,name VARCHAR(18),date DATE,PRIMARY KEY (id),INDEX tbl1_idx1 (date));
使用 CREATE INDEX 语句创建普通索引
可以通过 CREATE INDEX 语句为已有的表创建索引。
语法如下:
CREATE [UNIQUE] INDEX index_name ON table_name (column_name);
相关参数说明如下:
UNIQUE:可选,表示唯一索引。创建唯一索引时需要添加该关键字。index_name:指定待添加的索引的索引名。table_name:指定待创建索引的表的表名。column_name:指定对哪些列进行索引,指定多列时,各列之间用英文逗号分隔。
创建 tbl2 表后,再创建索引 tbl2_idx1 的示例如下:
创建表
tbl2。CREATE TABLE tbl2(id INT,name VARCHAR(20));在表
tbl2上创建索引tbl2_idx1。CREATE INDEX tbl2_idx1 ON tbl2(id);
使用 ALTER TABLE 语句创建普通索引
可以通过 ALTER TABLE 语句为已存在的表创建索引,且该语句支持一次增加多个索引。
语法如下:
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 的示例如下:
创建表
tbl3。CREATE TABLE tbl3(id INT,name VARCHAR(20));为表
tbl3创建索引tbl3_idx1。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)。
只能对空间数据类型的数据列创建空间索引。OceanBase 数据库支持的空间数据类型请参见 空间数据类型概述。
创建空间索引的列的列属性必须为
NOT NULL。如果不为
NOT NULL,您也可以通过ALTER TABLE语句先将该列的列属性修改为NOT NULL后再添加空间索引。修改列属性的具体操作可参见 定义列的约束类型。
使用 CREATE TABLE 语句创建空间索引
语法如下:
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 数据库支持的空间数据类型请参见 空间数据类型概述。INDEX|KEY:表示在该语句中,索引关键字使用INDEX或KEY都可以。index_name:指定待添加的索引的索引名。如果未指定,默认索引名与指定的列名相同。
创建 tbl1_g 表,同时添加空间索引 tbl1_g_idx1 的示例如下:
CREATE TABLE tbl1_g (id INT,name VARCHAR(18),g GEOMETRY NOT NULL SRID 4326,SPATIAL INDEX tbl1_g_idx1(g));
创建后,可以通过 SHOW INDEX 语句查看索引信息。
SHOW INDEX FROM tbl1_g;
查询结果如下:
+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
| 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 语句创建空间索引
语法如下:
CREATE SPATIAL INDEX index_name ON table_name(column_g_name);
相关参数说明如下:
table_name:指定待创建索引的表的表名。index_name:指定待添加的索引的索引名。column_g_name:指定对哪些列进行索引,指定多列时,各列之间用英文逗号分隔。待添加空间索引的列的列类型必须为空间数据类型。OceanBase 数据库支持的空间数据类型请参见 空间数据类型概述。
创建 tbl2_g 表后,再创建空间索引 tbl2_g_idx1 的示例如下:
创建表
tbl2_g。CREATE TABLE tbl2_g(id INT,name VARCHAR(20),g GEOMETRY NOT NULL SRID 4326);为表创建空间索引
tbl2_g_idx1。CREATE SPATIAL INDEX tbl2_g_idx1 ON tbl2_g(g);创建成功后,查看索引信息。
SHOW INDEX FROM tbl2_g;查询结果如下:
+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+ | 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 语句创建空间索引
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 数据库支持的空间数据类型请参见 空间数据类型概述。
创建 tbl3_g 表后,再创建空间索引 tbl3_g_idx1 的示例如下:
创建表
tbl3_g。CREATE TABLE tbl3_g(id INT,name VARCHAR(20),g GEOMETRY NOT NULL SRID 4326);在表上创建空间索引。
ALTER TABLE tbl3_g ADD SPATIAL INDEX tbl3_g_idx1(g);查看索引信息。
SHOW INDEX FROM tbl3_g;查询结果如下:
+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+ | 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:
CREATE TABLE sale(date_col date, sales_col int, name_col varchar(10));
如果您需要获取 3 月份的数据,则可以使用 Month() 函数来查询数据:
SELECT * FROM sale WHERE month(date_col) = 3;
该场景下,数据库需要为表中的每行计算 month(date_col),并过滤掉不符合 month(date_col) = 3 的行。如果您需要频繁地使用月份信息来过滤数据,则每次都需要重新计算 month(date_col),就会造成大量的开销。因此,您可以在 date_col 上创建一个函数索引,将 month(date_col) 存储到索引表中,来加速查询。
CREATE INDEX idx1 ON sale((month(date_col)));
您可以使用 CREATE TABLE 语句、CREATE INDEX 语句或 ALTER TABLE 语句来创建函数索引。函数索引也可以是唯一索引或空间索引。
函数索引使用限制
在 OceanBase 数据库的 MySQL 模式中,对函数索引的表达式进行了限制,禁止部分系统函数的表达式作为函数索引,具体的函数列表请参见 函数索引支持的系统函数列表 和 函数索引不支持的系统函数列表。
使用 CREATE TABLE 语句创建函数索引
可以在创建表时即为表创建函数索引。语法如下:
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 的示例如下:
CREATE TABLE tbl1_func (c1 int, c2 int, index tbl1_func_idx1 ((c1+1)), UNIQUE KEY ((c1+c2)));
创建成功后,可以通过 SHOW CREATE TABLE 语句查看建表语句,语句如下:
SHOW CREATE TABLE tbl1_func;
查询结果如下:
+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 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 语句创建函数索引
表创建成功后,可以为已有表创建函数索引。语法如下:
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,示例如下:
创建表
tbl2_func。CREATE TABLE tbl2_func(c1 int, c2 int);创建函数索引
tbl2_func_idx1。CREATE INDEX tbl2_func_idx1 on tbl2_func ((c1+c2 < 1));创建成功后,可以查看创建的函数索引。
SHOW INDEX FROM tbl2_func;结果如下:
+-----------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+---------------------+ | 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 语句创建函数索引
语法如下:
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。
创建表
tbl3_func。CREATE TABLE tbl3_func(c1 int, c2 int);为表创建 2 个函数索引。
ALTER TABLE tbl3_func ADD INDEX ((c1+1));ALTER TABLE tbl3_func ADD INDEX ((concat(c1,'a')));查看索引信息。
SHOW INDEX FROM tbl3_func;查询结果如下:
+-----------+------------+--------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------------+ | 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 语句在创建表时即为表创建列存索引。
语法如下:
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。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列的冗余数据。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 语句为已有的表创建列存索引。
语法如下:
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):指定索引的列存属性。WITH COLUMN GROUP(all columns, each column):指定创建行存列存冗余的索引。WITH COLUMN GROUP(all columns):指定创建行存索引。WITH COLUMN GROUP(each column):指定创建列存索引。
示例如下:
创建 tbl6 表后,再创建列存索引 idx1_tbl6_cg。
创建表
tbl6。CREATE TABLE tbl6(id INT, name VARCHAR(20), age INT);在表
tbl6上创建列存索引idx1_tbl6_cg,并且在索引表上存储age列的冗余数据。CREATE INDEX idx1_tbl6_cg ON tbl6(id) STORING(age) WITH COLUMN GROUP(each column);
使用 ALTER TABLE 语句创建列存索引
可以通过 ALTER TABLE 语句为已存在的表创建列存索引。
语法如下:
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):指定索引的列存属性。WITH COLUMN GROUP(all columns, each column):指定创建行存列存冗余的索引。WITH COLUMN GROUP(all columns):指定创建行存索引。WITH COLUMN GROUP(each column):指定创建列存索引。
示例如下:
创建表 tbl7 后,在创建列存索引 idx1_tbl6_cg。
创建表
tbl7。CREATE TABLE tbl7(id INT, name VARCHAR(20), age INT);为表
tbl7创建列存索引idx1_tbl7_cg,并且在索引表上存储age列的冗余数据。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 文档中的多个数组,如下所示:CAST(data->'$.arr[*][*]' AS UNSIGNED ARRAY)在这种情况下,所有匹配 JSON 表达式的值都作为单个平面数组存储在索引中。
多值索引不能是覆盖索引。
在多值键部分中允许的唯一类型的表达式是 JSON 表达式。表达式不必引用插入到索引列中的 JSON 文档中的现有元素,但必须在语法上有效。
由于同一个聚簇索引记录的索引记录在多值索引中分散,多值索引不支持范围扫描或仅索引扫描。
多值索引不允许在外键规范中使用。
不能为多值索引定义索引前缀。
不能在 Binary 类型的数据上定义多值索引。
多值索引对 Offline DDL 的支持情况请见Offline DDL。
使用 CREATE TABLE 语句创建多值索引
使用 CREATE TABLE 语句创建多值索引简化语法如下:
创建多值索引:
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)))
);
创建复合多值索引:
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。
创建多值示例如下:
创建表
json_tbl1,同时创建多值索引idx1_json_tbl1。CREATE TABLE json_tbl1(col1 INT, col2 VARCHAR(18), col3 JSON, INDEX idx1_json_tbl1((CAST(col3->'$.ipcode' AS UNSIGNED ARRAY))) );使用以下语句向表
json_tbl1中插入测试数据。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。
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 KEYCREATE 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 INTOCREATE 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示例表准备如下:
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示例如下: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示例如下: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;可更新视图
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。
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 创建唯一复合多值索引,复合多值索引:只允许一列是多值索引,其他列是普通列 |
示例分别如下:
创建表
json_tbl1,同时创建(非唯一)多值索引idx1_json_tbl1。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)));创建唯一多值索引
idx1_json_tbl2。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)));创建复合多值索引
idx1_json_tbl3。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)) );创建唯一复合多值索引
idx1_json_tbl4。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()查询示例。SELECT * FROM json_tbl1 WHERE 94507 MEMBER OF(col3->'$.ipcode');返回结果如下:
+------+------+-------------------------------------------------------------------+ | 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命令查看查询的执行计划。EXPLAIN SELECT * FROM json_tbl1 WHERE 94507 MEMBER OF(col3->'$.ipcode');返回结果如下:
+-------------------------------------------------------------------------------------------------------------------------------------------------------+ | 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()查询示例。SELECT * FROM json_tbl1 WHERE JSON_CONTAINS(col3->'$.ipcode', CAST('[94507,94582]' AS JSON));返回结果如下:
+------+------+-------------------------------------------------------------------+ | 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()查询示例。SELECT * FROM json_tbl1 WHERE JSON_OVERLAPS(col3->'$.ipcode', CAST('[94507,94582]' AS JSON));返回结果如下:
+------+------+-------------------------------------------------------------------+ | 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 语句来创建全文索引。
更多全文索引信息,参见 全文索引。
使用全文索引查询数据的信息,参见 全文查询。
全文索引使用限制及注意事项
非分区表和分区表上有无主键都可以创建全文索引,创建全文索引限制如下:
- 全文索引仅支持应用于
CHAR、VARCHAR和TEXT类型的列。 - 当前版本只支持创建局部(
LOCAL)全文索引。 - 创建全文索引时不可以指定
UNIQUE关键字。 - 如果要创建涉及多列的全文索引,则必须确保这些列具有相同的字符集。
- 全文索引对 Offline DDL 的支持情况请见Offline DDL。
使用 CREATE TABLE 语句创建全文索引
通过 CREATE TABLE 语句在创建表时即为表创建全文索引,简化语法如下:
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。
相关参数说明如下:
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 smartmax_word
可以使用 TOKENIZE 函数查看文本按照指定的分词器及 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。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设置分词器属性。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 语句为已有的表创建全文索引,语法如下:
CREATE FULLTEXT INDEX index_name ON table_name (column_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 INDEX 语法信息,参见 CREATE INDEX。
相关参数说明如下:
index_name:指定待添加的索引的索引名。table_name:指定待创建索引的表的表名。column_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 smartmax_word
可以使用 TOKENIZE 函数查看文本按照指定的分词器及 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:可选项,指定创建局部索引。
示例如下:
创建 tbl3 表后,再创建全文索引 ft_idx1_tbl3。
创建表
tbl3。CREATE TABLE tbl3(col1 INT, col2 VARCHAR(4096));在表
tbl3上创建全文索引ft_idx1_tbl3,指定全文索引的分词器为IK,同时通过PARSER_PROPERTIES设置分词器属性。CREATE FULLTEXT INDEX ft_idx1_tbl3 ON tbl3(col2) WITH PARSER IK PARSER_PROPERTIES=(ik_mode='max_word');
使用 ALTER TABLE 语句创建全文索引
通过 ALTER TABLE 语句为已有的表添加全文索引,语法如下:
ALTER TABLE table_name ADD FULLTEXT [INDEX | KEY] [index_name](column_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
更多通过 ALTER TABLE 语句为已有的表添加全文索引的语法信息,参见 ALTER TABLE。
相关参数说明如下:
table_name:指定待创建索引的表的表名。INDEX | KEY:可选项,表示在该语句中,索引关键字使用INDEX或KEY都可以,缺省值为KEY。index_name:可选项,指定待创建的索引的索引名。如果未指定,默认索引名与指定的列名相同。column_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 smartmax_word
可以使用 TOKENIZE 函数查看文本按照指定的分词器及 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:可选项,指定创建局部索引。
示例如下:
创建表 tbl4 后,然后再添加全文索引 ft_idx1_tbl4。
创建表
tbl4。CREATE TABLE tbl4(col1 INT, col2 TEXT);为表
tbl4添加全文索引ft_idx1_tbl4,指定全文索引的分词器为BENG,同时通过PARSER_PROPERTIES设置分词器属性。ALTER TABLE tbl4 ADD FULLTEXT INDEX ft_idx1_tbl4(col2) WITH PARSER BENG PARSER_PROPERTIES=(min_token_size=2, max_token_size=64);
相关文档
更多 MySQL 模式下索引相关的内容,参见以下信息: