
# 管理索引
#### 背景信息
索引可以提高数据的访问速度，但同时也增加了插入、更新和删除操作的处理时间。因此，在创建索引前需评估是否创建索引，需决策索引字段的选择。需要分析应用程序的业务处理、数据使用、经常被用作查询的条件或者被要求排序的字段来确定是否建立索引。
索引建立在数据库表中的某些列上。因此，在创建索引时，需要评估目标列的选择标准。可以通过以下条件判断是否创建索引，选择创建索引的列。
- 在经常需要搜索查询的列上创建索引，可以加快搜索的速度。
- 在作为主键的列上创建索引，强制要求主键唯一、强制要求主键有序排列。
- 在经常使用连接的列上创建索引，可以加快连接的速度。
- 在经常需要根据范围进行搜索的列上创建索引，因为索引已经排序，其指定的范围是连续的。
- 在经常需要排序的列上创建索引，因为索引已经排序，这样查询可以利用索引的排序，加快排序查询时间。
- 在经常使用WHERE子句的列上创建索引，加快条件的判断速度。
- 为经常出现在关键字ORDER BY、GROUP BY和DISTINCT后面的字段建立索引。
  ![](https://support.huaweicloud.com/distributed-devg-v8-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 索引创建成功后，系统会自动判断何时引用索引。当系统认为使用索引比顺序扫描更快时，就会使用索引。
  
  - 索引创建成功后，必须和表保持同步以保证能够准确地找到新数据，这样就增加了数据操作的负荷。因此请定期删除无用的索引。
  
  - 分区表索引分为LOCAL索引与GLOBAL索引，一个LOCAL索引对应一个具体分区，而GLOBAL索引则对应整个分区表。
    
 
- 在开启逻辑复制的场景下，如需创建包含系统列的主键索引，必须将该表的REPLICA IDENTITY属性设置为FULL或是使用USING INDEX指定不包含系统列的、唯一的、非局部的、不可延迟的、仅包括标记为NOT NULL的列的索引。
#### 操作步骤
操作前请先创建分区表，步骤请参见[管理分区表](https://support.huaweicloud.com/distributed-devg-v8-gaussdb/gaussdb-12-0036.html#ZH-CN_TOPIC_0000002527825750)。
- 创建索引，具体操作请参见[CREATE INDEX](https://support.huaweicloud.com/distributed-devg-v8-gaussdb/gaussdb-12-0549.html#ZH-CN_TOPIC_0000002527986148)。
  - 创建分区表索引tpcds_web_returns_p2_index1，不指定索引分区的名称。
    ```
    gaussdb=# CREATE INDEX tpcds_web_returns_p2_index1 ON tpcds.web_returns_p2 (ca_address_id) LOCAL;
    ```
    当结果显示为如下信息，则表示创建成功。
    ```
    CREATE INDEX
    ```
    
  
  - 创建分区表索引tpcds_web_returns_p2_index2，并指定索引分区的名称。
    ```
    gaussdb=# CREATE INDEX tpcds_web_returns_p2_index2 ON tpcds.web_returns_p2 (ca_address_sk) LOCAL
    (
        PARTITION web_returns_p2_P1_index,
        PARTITION web_returns_p2_P2_index TABLESPACE example3,
        PARTITION web_returns_p2_P3_index TABLESPACE example4,
        PARTITION web_returns_p2_P4_index,
        PARTITION web_returns_p2_P5_index,
        PARTITION web_returns_p2_P6_index,
        PARTITION web_returns_p2_P7_index,
        PARTITION web_returns_p2_P8_index
    ) TABLESPACE example2;
    ```
    当结果显示为如下信息，则表示创建成功。
    ```
    CREATE INDEX
    ```
    
   
- 修改索引分区的表空间
  - 修改索引分区*web_returns_p2_P2_index* 的表空间为*example1* 。
    ```
    gaussdb=# ALTER INDEX tpcds.tpcds_web_returns_p2_index2 MOVE PARTITION web_returns_p2_P2_index TABLESPACE example1;
    ```
    当结果显示为如下信息，则表示修改成功。
    ```
    ALTER INDEX
    ```
    
  
  - 修改索引分区*web_returns_p2_P3_index* 的表空间为*example2* 。
    ```
    gaussdb=# ALTER INDEX tpcds.tpcds_web_returns_p2_index2 MOVE PARTITION web_returns_p2_P3_index TABLESPACE example2;
    ```
    当结果显示为如下信息，则表示修改成功。
    ```
    ALTER INDEX
    ```
    
   
- 重命名索引分区
  执行如下命令对索引分区web_returns_p2_P8_index重命名web_returns_p2_P8_index_new。
  ```
  gaussdb=# ALTER INDEX tpcds.tpcds_web_returns_p2_index2 RENAME PARTITION web_returns_p2_P8_index TO web_returns_p2_P8_index_new;
  ```
  当结果显示为如下信息，则表示重命名成功。
  ```
  ALTER INDEX
  ```
  
- 查询索引
  - 执行如下命令查询系统和用户定义的所有索引。
    ```
    gaussdb=# SELECT RELNAME FROM PG_CLASS WHERE RELKIND='i';
    ```
    
  
  - 执行如下命令查询指定索引的信息。
    ```
    gaussdb=# \di+ tpcds.tpcds_web_returns_p2_index2
    ```
    
   
- 删除索引
  ```
  gaussdb=# DROP INDEX tpcds.tpcds_web_returns_p2_index1;
  gaussdb=# DROP INDEX tpcds.tpcds_web_returns_p2_index2;
  ```
  当结果显示为如下信息，则表示删除成功。
  ```
  DROP INDEX
  ```
  
 
#### 索引介绍
GaussDB支持4种创建索引的方式，请参见[表1]。
 表1索引方式 
| 索引方式  | 描述                                                                                                                              |
|:---|:---|
| 唯一索引  | 可用于约束索引属性值的唯一性，或者属性组合值的唯一性。如果一个表声明了唯一约束或者主键，则GaussDB自动在组成主键或唯一约束的字段上创建唯一索引（可能是多字段索引），以实现这些约束。目前，GaussDB只有B-Tree及UBTree可以创建唯一索引。 |
| 多字段索引 | 一个索引可以定义在表中的多个属性上。目前，GaussDB中的B-Tree支持多字段索引，且最多可在32个字段上创建索引。                                                                    |
| 部分索引  | 建立在一个表的子集上的索引，这种索引方式只包含满足条件表达式的元组。                                                                                              |
| 表达式索引 | 索引建立在一个函数或者从表中一个或多个属性计算出来的表达式上。表达式索引只有在查询时使用与创建时相同的表达式才会生效。                                                                     |
   
- 创建一个普通表
  ```
  gaussdb=# CREATE TABLE tpcds.customer_address_bak AS TABLE tpcds.customer_address;
  INSERT 0 0
  ```
  

- 创建普通索引
  如果对于tpcds.customer_address_bak表，需要经常进行以下查询。
  ```
  gaussdb=# SELECT ca_address_sk FROM tpcds.customer_address_bak WHERE ca_address_sk=14888;
  ```
  当数据库系统执行tpcds.customer_address_bak表的查询时，若采用全表扫描方式逐行匹配WHERE条件，在表数据量庞大但匹配行极少数（甚至为零）的场景下，该操作将产生显著性能瓶颈。若数据库系统在ca_address_sk属性上维护一个索引，用于快速定位匹配的元组，则数据库系统只需遍历少量索引节点即可获取匹配元组，从而大幅提升查询效率。同样，在数据库中进行更新和删除操作时，索引也可以提升这些操作的性能。
  执行如下命令创建索引。
  ```
  gaussdb=# CREATE INDEX index_wr_returned_date_sk ON tpcds.customer_address_bak (ca_address_sk);
  CREATE INDEX
  ```
  
- 创建唯一索引 在表tpcds.ship_mode_t1中的SM_SHIP_MODE_SK字段上创建唯一索引。
  ```
  gaussdb=# CREATE UNIQUE INDEX ds_ship_mode_t1_index1 ON tpcds.ship_mode_t1(SM_SHIP_MODE_SK);
  ```
  
- 创建多字段索引
  假如用户需要经常查询表tpcds.customer_address_bak中ca_address_sk是5050，且ca_street_number小于1000的记录，使用以下命令进行查询。
  ```
  gaussdb=# SELECT ca_address_sk,ca_address_id FROM tpcds.customer_address_bak WHERE ca_address_sk = 5050 AND ca_street_number < 1000;
  ```
  执行如下命令在字段ca_address_sk和ca_street_number上定义一个多字段索引。
  ```
  gaussdb=# CREATE INDEX more_column_index ON tpcds.customer_address_bak(ca_address_sk ,ca_street_number );
  CREATE INDEX
  ```
  
- 创建部分索引 如果只需要查询ca_address_sk为5050的记录，可以创建部分索引来提升查询效率。
  ```
  gaussdb=# CREATE INDEX part_index ON tpcds.customer_address_bak(ca_address_sk) WHERE ca_address_sk = 5050;
  CREATE INDEX
  ```
  
- 创建表达式索引
  假如经常需要查询ca_street_number小于1000的信息，执行如下命令进行查询。
  ```
  gaussdb=# SELECT * FROM tpcds.customer_address_bak WHERE trunc(ca_street_number) < 1000;
  ```
  可以为上述的查询创建表达式索引。
  ```
  gaussdb=# CREATE INDEX para_index ON tpcds.customer_address_bak (trunc(ca_street_number));
  CREATE INDEX
  ```
  
- 删除tpcds.customer_address_bak表
  ```
  gaussdb=# DROP TABLE tpcds.customer_address_bak;
  DROP TABLE
  ```
  
 
