暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

OceanBase Cloud快速入门第31期:如何创建索引?

欢迎访问OceanBase官网获取更多信息:https://www.oceanbase.com/


索引简介

索引也叫二级索引,是一种可选的表结构。OceanBase 数据库采用的是聚集索引表模型,对于用户指定的主键,系统会自动生成主键索引,而对于用户创建的其他索引,则是二级索引。您可以根据自身业务需要来决定在哪些字段上创建索引,以便加快在这些字段上的查询速度。

索引可以分为唯一索引和非唯一索引:

  • 唯一索引保证在表内的索引列上不存在两行有完全相同的值。在 OceanBase 数据库中,NULL 值也会存储在索引中。

  • 非唯一索引可能存在完全相同的值。

对于分区表,索引还可以分为局部索引和全局索引:

  • 局部索引是针对单个分区上的数据创建的索引,故局部索引的索引键值与表中的数据是一一对应的关系,即局部索引上的一个分区一定对应到一个表分区,它们具有相同的分区规则。因此,对于局部唯一索引而言,它只能保证对应分区内部的唯一性,而无法保证表数据的全局唯一性。

  • 全局索引的分区规则与表分区相互独立,因此索引表中一个分区的索引值可能对应着主表的多个分区内的数据。

索引创建准备

在创建索引前,您需要确认以下事项:

  • 请确认您已连接到数据库的 MySQL 租户,连接数据库的操作请参见 连接数据库

    说明

    当前登录租户所属的租户模式可以由 sys 租户通过查询 oceanbase.DBA_OB_TENANTS 视图进行确认。

  • 请确认您已拥有 INDEX 权限以及待添加索引的表的 ALTER 权限。

  • 请确认已创建数据库,创建数据库的操作请参见 创建数据库

  • 请确认已创建表,创建表的操作请参见 创建表

索引创建建议

  • 对经常更新的表要避免对其进行过多的索引,对经常用于查询的字段应该创建索引。

  • 数据量小的表建议不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。

  • 当修改性能远远大于检索性能时,不建议创建索引。

  • 创建高效索引:

    • 索引要全部包含所需 查询的列,包含的列越全越好,这样可以尽可能的减少回表的行数。

    • 等值条件永远放在最前面。

    • 过滤与排序数据量大的放前面。

创建唯一索引

如果需要索引列上不存在重复的值,可以创建唯一索引。

您可以使用 CREATE UNIQUE INDEX 语句,再参考以下的要求为已存在的表创建唯一索引。

也可以使用 ALTER TABLE 语句在修改表时,参考以下要求为已存在的表添加唯一索引。该语句可以一次添加多个索引,索引关键字用 INDEX 或 KEY 都可以。

以下是创建唯一索引需要遵循的要求:

  • 在 OceanBase 数据库中,索引名称必须在表范围内保证唯一。

  • 唯一索引可以有多个,但其列值必须唯一。

  • 索引列的值允许为 NULL 值。

示例:

  • 使用 CREATE UNIQUE INDEX 语句为表创建唯一索引。

    obclient> CREATE TABLE test(c1 INT, c2 INT, c3 INT, c4 INT, PRIMARY KEY  (c1));
    Query OK, 0 rows affected
    
    obclient> CREATE UNIQUE INDEX idx1 ON test(c2);
    Query OK, 0 rows affected
    
  • 使用 ALTER TABLE 语句为表创建唯一索引。

    obclient> CREATE TABLE test(c1 INT, c2 INT, c3 INT, c4 INT, PRIMARY KEY  (c1));
    Query OK, 0 rows affected
    
    obclient> ALTER TABLE test ADD UNIQUE INDEX idx2 (c2);
    Query OK, 0 row affected
    

创建非唯一索引

您可以使用 CREATE INDEX 语句,再参考以下的要求为表创建非唯一索引。

也可以使用 ALTER TABLE 语句在修改表时,再参考以下要求为已存在的表添加非唯一索引。该语句可以一次增加多个索引,索引关键字用 INDEX 或 KEY 都可以。

以下是创建非唯一索引需要遵循的要求:

  • 在 OceanBase 数据库中,索引名称必须在表范围内保证唯一。

  • 索引列的值可以重复,可以为 NULL 值。

示例:

  • 使用 CREATE INDEX 语句为表创建非唯一索引。

    obclient> CREATE TABLE test(c1 INT, c2 INT, c3 INT, c4 INT, PRIMARY KEY(c1));
    Query OK, 0 rows affected
    
    obclient> CREATE INDEX idx1 ON test(c2);
    Query OK, 0 rows affected
    
  • 使用 ALTER TABLE 语句为表创建非唯一索引。

    obclient> CREATE TABLE test(c1 INT, c2 INT, c3 INT, c4 INT, PRIMARY KEY  (c1));
    Query OK, 0 rows affected
    
    obclient> ALTER TABLE test ADD INDEX idx2 (c1,c2);
    Query OK, 0 row affected
    

创建局部索引

局部索引又名分区索引,创建局部索引的关键字是 LOCAL。局部索引的分区键等同于表的分区键,局部索引的分区数等同于表的分区数,所以局部索引的分区机制和表的分区机制一样。支持创建局部索引和局部唯一索引。如果要使用局部唯一索引去对数据的唯一性做约束,那么局部唯一索引中必须包含表分区键。

请使用 CREATE INDEX 语句结合 LOCAL 关键字,再参考以下要求为已存在的表创建局部索引。

请使用 CREATE UNIQUE INDEX 语句结合 LOCAL 关键字,再参考以下要求为已存在的表创建局部唯一索引。

以下是创建局部索引需要遵循的要求:

  • 在 OceanBase 数据库中,索引名称必须在表范围内保证唯一。

  • 在 OceanBase 数据库的 MySQL 模式中,如果索引属性关键字没有指定,则默认的索引属性是 LOCAL 属性,即创建的索引为局部索引。

  • 如果要创建局部唯一索引,则局部唯一索引中必须包括表分区函数中的所有列。

示例:

  • 创建局部索引。

    obclient> CREATE TABLE tbl1_h(col1 INT PRIMARY KEY,col2 INT)
           PARTITION BY HASH(col1) PARTITIONS 5;
    Query OK, 0 rows affected
    
    obclient> CREATE INDEX tbl1_h_idx1 ON tbl1_h(col2) LOCAL;
    Query OK, 0 rows affected
    
  • 创建局部唯一索引。

    obclient> CREATE TABLE tbl2_f_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))
          ); 
    Query OK, 0 rows affected
    
    obclient> CREATE UNIQUE INDEX tbl2_f_rl_idx1 ON tbl2_f_rl(col1,col2) LOCAL;
    Query OK, 0 rows affected
    

创建全局索引

创建全局索引的关键字是 GLOBAL

请使用 CREATE INDEX 语句结合 GLOBAL 关键字,再参考以下要求为已存在的表创建全局索引。

请使用 CREATE UNIQUE INDEX 语句结合 GLOBAL 关键字,再参考以下要求为已存在的表创建全局唯一索引。

以下是创建全局索引需要遵循的要求:

  • 在 OceanBase 数据库中,索引名称必须在表范围内保证唯一。

  • 在 OceanBase 数据库的 MySQL 模式中,如果索引属性关键字没有指定,则默认的索引属性是 LOCAL 属性,即创建的索引为局部索引。

  • 全局索引的分区规则不一定要与表分区规则保持一致。

  • 如果全局索引的分区规则和主表的分区规则相同并且分区数相同,建议创建一个局部索引。 一方面是因为全局索引的维护代价更大;另一方面是因为全局索引无法保证和主表分区的物理位置相同,除非将其和主表指定在一个表组中。

  • 除了主键外,如果还希望其他列的组合能满足全局唯一性的要求,需要使用全局唯一索引来实现。

示例:

  • 创建全局索引。

    创建 Hash 分区一级分区表 tbl1_h,并为其创建采用 Range 分区的全局索引 tbl1_h_idx1

    obclient> CREATE TABLE tbl1_h(col1 INT PRIMARY KEY,col2 INT)
          PARTITION BY HASH(col1) PARTITIONS 5;
    Query OK, 0 rows affected
    
    obclient> CREATE INDEX tbl1_h_idx1 ON tbl1_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)
          );
    Query OK, 0 rows affected
    
  • 创建全局唯一索引。

    创建非模板化 Range + List 分区表 tbl2_f_rl,并为其创建全局唯一索引 tbl2_f_rl_idx1

    obclient> CREATE TABLE tbl2_f_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))
          ); 
    Query OK, 0 rows affected
    
    obclient> CREATE UNIQUE INDEX tbl2_f_rl_idx1 ON tbl2_f_rl(col1) GLOBAL;
    Query OK, 0 rows affected
    

创建空间索引

OceanBase 数据库支持创建常规索引的语法创建空间索引,但使用 SPATIAL 关键字。

说明

空间索引中引用数据类型的列必须指定 SRID 和 NOT NULL,否则创建成功的索引无法生效。

您可以使用以下方法创建空间索引:

  • CREATE TABLE 时添加空间索引:

    CREATE TABLE table_name(column_g_name GEOMETRY NOT NULL,[column_name data_type,...] SPATIAL INDEX index_name(column_g_name));
    
  • ALTER TABLE 时添加空间索引:

ALTER TABLE table_name ADD SPATIAL INDEX index_name(column_g_name);

说明

OceanBase 数据库暂不支持通过 ALTER TABLE 来修改列的 SRID 属性,因此需要建表的时候定义好空间列的 SRID 属性,才能让空间索引生效。

  • 通过 CREATE INDEX 语句创建空间索引:

    CREATE SPATIAL INDEX index_name ON table_name(column_g_name);
    

    MySQL 租户里,索引名称在表范围内不能重复,查看索引可以通过命令 SHOW INDEX

参数解释:

参数描述
index_name索引名称。
table_name表名称。
column_name列名称。
data_type数据类型。
column_g_name空间数据类型的列名。

示例

  • 创建 tbl1_g 表,同时添加索引 tbl1_g_idx1

    obclient [test]> CREATE TABLE tbl1_g(id INT,name VARCHAR(18),g GEOMETRY NOT NULL SRID 0,SPATIAL INDEX tbl1_g_idx1(g));
    Query OK, 0 rows affected
    
    obclient [test]> 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
    
  • 创建 tbl2_g 表,然后再修改表时增加索引 tbl2_g_idx1

    obclient [test]> CREATE TABLE tbl2_g(id INT,name VARCHAR(20),g GEOMETRY NOT NULL SRID 0);
    Query OK, 0 rows affected
    
    obclient [test]> ALTER TABLE tbl2_g ADD SPATIAL INDEX tbl2_g_idx1(g);
    Query OK, 0 rows affected
    
    obclient [test]> 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
    
  • 创建 tbl3_g 表,并通过 CREATE INDEX 语句创建索引 tbl3_g_idx1

    obclient [test]> CREATE TABLE tbl3_g(id INT,name VARCHAR(20),g GEOMETRY NOT NULL SRID 0);
    Query OK, 0 rows affected (0.060 sec)
    
    obclient [test]> CREATE INDEX tbl3_g_idx1 ON tbl3_g(g);
    Query OK, 0 rows affected (0.568 sec)
    
    obclient [test]> 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


欢迎访问OceanBase官网获取更多信息:https://www.oceanbase.com/

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论