创建索引
本文将向您介绍如何使用 SQL 语句来创建索引,同时介绍创建索引的前提条件、索引简介、限制和建议等,并提供一些示例。
本文主要介绍使用 CREATE INDEX 语句创建索引,多值索引除外。多值索引仅支持在创建表时创建。其他创建索引的方式请参见CREATE TABLE 或 ALTER TABLE 语句。
索引简介
索引也叫二级索引,是一种可选的表结构。seekdb 采用的是聚集索引表模型,对于用户指定的主键,系统会自动生成主键索引,而对于用户创建的其他索引,则是二级索引。您可以根据自身业务需要来决定在哪些字段上创建索引,以便加快在这些字段上的查询速度。
更多有关 seekdb 索引的信息,请参见 索引简介。
前提条件
在创建索引前,您需要确认以下事项:
-
您已部署 seekdb。更多有关部署 seekdb 的信息,请参见 部署概述。
-
您已连接到 seekdb。更多连接数据库的信息,请参见 连接方式概述。
-
您已创建数据库。更多有关创建数据库的信息,请参见 创建数据库。
-
您已创建表。更多有关创建表的信息,请参见 创建表。
-
您已拥有
INDEX权限。查看当前用户权限的相关操作请参见 查看用户权限。如果不具备该权限,请联系管理员为您授权,用户授权的相关操作请参见 直接授予权限。
创建索引的限制
-
在 seekdb 中,索引名称必须在数据库(DataBase)的范围内保证唯一。
-
索引名称的长度不能超过 64 字节。
-
唯一索引使用限制:
-
在一个表中可以创建多个唯一索引,但是每个唯一索引所对应的列值都必须保持唯一。
-
如果除了主键之外,还希望其他列的组合满足全局唯一性的要求,需要使用全局唯一索引来实现。
-
在使用局部 唯一索引时,索引必须包含表的分区函数中的所有列。
-
-
在使用全局索引时,全局索引的分区规则不一定需要与表的分区规则完全相同或一致。
-
空间索引使用限制:
-
空间索引仅支持局部索引,不支持全局索引。
-
创建空间索引的列必须定义为
SRID属性,否则,在该列上添加的空间索引在后续查询时会无法生效。关于SRID相关的介绍,请参见 空间参考系统(SRS)。 -
只能对空间数据类型的数据列创建空间索引。seekdb 支持的空间数据类型请参见 空间数据类型概述。
-
创建空间索引的列的列属性必须为
NOT NULL。如果不为NOT NULL,您也可以通过ALTER TABLE语句先将该列的列属性修改为NOT NULL后再添加空间索引。修改列属性的具体操作可参见 定义列的约束类型。 -
seekdb 暂不支持通过
ALTER TABLE来修改列的SRID属性,因此需要建表的时候定义好空间列的SRID属性,才能让空间索引生效。
-
-
全文索引使用限制及注意事项
非分区表和分区表上有无主键都可以创建全文索引,创建全文索引限制如下:
- 全文索引仅支持应用于
CHAR、VARCHAR和TEXT类型的列。 - 当前版本只支持创建局部(
LOCAL)全文索引。 - 创建全文索引时不可以指定
UNIQUE关键字。 - 如果要创建涉及多列的全文索引,则必须确保这些列具有相同的字符集。
- 全文索引仅支持应用于
创建索引的建议
-
建议使用能够简洁地描述索引所涵盖的列和用途的名称,例如,
idx_customer_name。更多命名信息,请参见 对象命名规范综述。 -
如果全局索引的分区规则和主表的分区规则相同并且分区数相同,建议创建一个局部索引。
-
建议并行下发创建索引的 SQL 语句条数,不要超过 seekdb 的核数上限。例如,seekdb 规格为 4 核(4C),则建议并发创建索引不超过 4 条。
-
对经常更新的表要避免对其进行过多的索引,对经常用于查询的字段应该创建索引。
-
数据量小的表建议不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。
-
当修改性能远远大于检索性能时,不建议创建索引。
-
创建高效索引:
-
索引要全部包含所需查询的列,包含的列越全越好,这样可以尽可能的减少回表的行数。
-
等值条件永远放在最前面。
-
过滤与排序数据量大的放前面。
-
使用命令行创建索引
请使用 CREATE INDEX 语句创建索引。
您可以使用 SHOW INDEX FROM table_name; 语句查看表中索引的信息,其中 table_name 为表名。
示例
示例一:创建唯一索引
如果需要索引列上不存在重复的值,可以创建唯一索引。
使用以下 SQL 语句创建一个名为 tbl1 的表,并为表 tbl1 创建一个基于 col2 列的唯一索引。
-
创建表
tbl1。CREATE TABLE tbl1(col1 INT, col2 INT, col3 VARCHAR(50), PRIMARY KEY (col1)); -
在表
tbl1上基于col2列创建一个名为idx_tbl1_col2的唯一索引。CREATE UNIQUE INDEX idx_tbl1_col2 ON tbl1(col2); -
查看表
tbl1索引信息。SHOW INDEX FROM tbl1;返回结果如下:
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| tbl1 | 0 | PRIMARY | 1 | col1 | A | NULL | NULL | NULL | | BTREE | available | | YES | NULL |
| tbl1 | 0 | idx_tbl1_col2 | 1 | col2 | A | NULL | NULL | NULL | YES | BTREE | available | | YES | NULL |
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
2 rows in set
示例二:创建非唯一索引
使用以下 SQL 语句创建一个名为 tbl2 的表,并为表 tbl2 创建一个基于 col2 列的索引。
-
创建表
tbl2。CREATE TABLE tbl2(col1 INT, col2 INT, col3 VARCHAR(50), PRIMARY KEY (col1)); -
在表
tbl2上基于col2列创建一个名为idx_tbl2_col2的索引。CREATE INDEX idx_tbl2_col2 ON tbl2(col2); -
查看表
tbl2索引信息。SHOW INDEX FROM tbl2;返回结果如下:
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| tbl2 | 0 | PRIMARY | 1 | col1 | A | NULL | NULL | NULL | | BTREE | available | | YES | NULL |
| tbl2 | 1 | idx_tbl2_col2 | 1 | col2 | A | NULL | NULL | NULL | YES | BTREE | available | | YES | NULL |
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
2 rows in set
示例三:创建局部索引
局部索引又名分区索引,创建局部索引的关键字是 LOCAL。局部索引的分区键等同于表 的分区键,局部索引的分区数等同于表的分区数,所以局部索引的分区机制和表的分区机制一样。支持创建局部索引和局部唯一索引。如果要使用局部唯一索引去对数据的唯一性做约束,那么局部唯一索引中必须包含表分区键。
使用以下 SQL 语句创建一个名为 tbl3_rl 的二级分区表,并为表 tbl3_rl 创建一个基于 col1 和 col2 列的局部唯一索引索引。
-
创建 Range + List 二级分区表
tbl3_rl。CREATE TABLE tbl3_rl(col1 INT,col2 INT)
PARTITION BY RANGE(col1)
SUBPARTITION BY LIST(col2)
(PARTITION p0 VALUES LESS THAN(100)
(SUBPARTITION sp0 VALUES IN(1,3),
SUBPARTITION sp1 VALUES IN(4,6),
SUBPARTITION sp2 VALUES IN(7,9)),
PARTITION p1 VALUES LESS THAN(200)
(SUBPARTITION sp3 VALUES IN(1,3),
SUBPARTITION sp4 VALUES IN(4,6),
SUBPARTITION sp5 VALUES IN(7,9))
); -
在表
tbl3_rl上基于col1和col2列 创建一个名为idx_tbl3_rl_col1_col2的索引。CREATE UNIQUE INDEX idx_tbl3_rl_col1_col2 ON tbl3_rl(col1,col2) LOCAL; -
查看表
tbl3_rl索引信息。SHOW INDEX FROM tbl3_rl;返回结果如下:
+---------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| tbl3_rl | 0 | idx_tbl3_rl_col1_col2 | 1 | col1 | A | NULL | NULL | NULL | YES | BTREE | available | | YES | NULL |
| tbl3_rl | 0 | idx_tbl3_rl_col1_col2 | 2 | col2 | A | NULL | NULL | NULL | YES | BTREE | available | | YES | NULL |
+---------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
2 rows in set
示例四:创建全局索引
创建全局索引的关键字是 GLOBAL。
使用以下 SQL 语句创建一个名为 tbl4_h 的一级分区表,并为表 tbl4_h 创建一个基于 col2 列的 全局索引。
-
创建 Hash 分区一级分区表
tbl4_h。CREATE TABLE tbl4_h(col1 INT PRIMARY KEY,col2 INT)
PARTITION BY HASH(col1) PARTITIONS 5; -
在表
tbl4_h上创建一个名为idx_tbl4_h_col2的全局索引,该索引是基于col2列的 Range 分区索引。CREATE INDEX idx_tbl4_h_col2 ON tbl4_h(col2) GLOBAL
PARTITION BY RANGE(col2)
(PARTITION p0 VALUES LESS THAN(100),
PARTITION p1 VALUES LESS THAN(200),
PARTITION p2 VALUES LESS THAN(300)
); -
查看表
tbl4_h索引信息。SHOW INDEX FROM tbl4_h;返回结果如下:
+--------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| tbl4_h | 0 | PRIMARY | 1 | col1 | A | NULL | NULL | NULL | | BTREE | available | | YES | NULL |
| tbl4_h | 1 | idx_tbl4_h_col2 | 1 | col2 | A | NULL | NULL | NULL | YES | BTREE | available | | YES | NULL |
+--------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
2 rows in set
示例五:创建空间索引
空间索引是一种用于处理和优化空间数据的数据库索引。它被广泛应用于地理信息系统(GIS)和位置数据的存储和查询。seekdb 支持创建常规索引的语法创建空间索引,但空间索引需要使用 SPATIAL 关键字。
使用以下 SQL 语句创建一个名为 tbl5 的表,并为表 tbl5 创建一个基于 g 列的空间索引。
-
创建表
tbl5。CREATE TABLE tbl5(id INT,name VARCHAR(20),g GEOMETRY NOT NULL SRID 0); -
在表
tbl5上基于g列创建一个名为idx_tbl5_g的空间索引。CREATE INDEX idx_tbl5_g ON tbl5(g); -
查看表
tbl5索引信息。SHOW INDEX FROM tbl5;返回结果如下:
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
| tbl5 | 1 | idx_tbl5_g | 1 | g | A | NULL | NULL | NULL | | SPATIAL | available | | YES | NULL |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+------------+
1 row in set
示例六:创建函数索引
基于表中一列或多列的值进行计算后的结果建立的索引称为函数索引。函数索引是一种优化技术,使用函数索引可以在查询时快速定位匹配的函数值,从而避免重复计算,提高查询效率。
在 seekdb 中,对函数索引的表达式进行了限制,禁止部分系统函数的表达式作为函数索引,具体的函数列表请参见 函数索引支持的系统函数列表 和 函数索引不支持的系统函数列表。
Session 变量固化机制
函数索引中的 Session 变量固化机制确保索引在创建时和使用时的计算语义完全一致,避免因 Session 环境变化导致"索引命中但结果错误"。
工作原理
当创建函数索引时,系统会自动分析索引表达式,识别该表达式依赖哪些 Session 变量(如 time_zone、sql_mode、collation_connection 等),并将这些变量的当前值保存到索引元数据中。
当查询命中函数索引时:
- 系统根据索引表达式的
local_session_var_id获取创建索引时保存的 Session 变量快照 - 在表达式类型推导和计算时,使用保存的变量值而不是当前 Session 的变量值
- 确保计算结果与创建索引时完全一致