

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 管理索引
<a name="working.manage-indexes"></a>

**重要**  
终止支持通知：现有客户将能够使用 Amazon QLDB，直到 2025 年 7 月 31 日终止支持。有关更多详细信息，请参阅[将亚马逊 QLDB 账本迁移到亚马逊 Aurora PostgreSQL](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)。

本部分介绍如何在 Amazon QLDB 中创建、描述和删除索引。可以为每个表创建的索引数量的限额在[Amazon QLDB 资源中的限额和限制](limits.md#limits.fixed)中定义。

**Topics**
+ [创建索引](#working.manage-indexes.create)
+ [描述索引](#working.manage-indexes.describe)
+ [删除索引](#working.manage-indexes.drop)
+ [常见错误](#working.manage-indexes.errors)

## 创建索引
<a name="working.manage-indexes.create"></a>

如[创建表与索引](working.create.md#working.create.tables-indexes)中所述，您可以使用 [CREATE INDEX](ql-reference.create-index.md) 语句在表上为指定的顶级字段创建索引，如下所示。表名和索引字段名称均为区分大小写。

```
CREATE INDEX ON VehicleRegistration (VIN)
```

```
CREATE INDEX ON VehicleRegistration (LicensePlateNumber)
```

您在表上创建的每个索引都包含一个系统分配的唯一 ID。若要查找此索引 ID，请参阅以下部分 [描述索引](#working.manage-indexes.describe)。

**重要**  
QLDB 需要索引才能高效查找文档。如果没有索引，QLDB 在读取文档时需进行全表扫描。这可能会导致大型表出现性能问题，包括并发冲突与事务超时。  
为避免表扫描，必须在索引字段或文档 ID 上使用*相等*运算符（`=`或`IN`）运行带有`WHERE`谓词子句的语句。有关更多信息，请参阅 [优化查询性能](working.optimize.md)。

创建索引时应注意以下限制：
+ 只能在单个顶级字段创建索引。不支持复合索引、嵌套索引、唯一索引以及基于函数的索引。
+ 您可以为任何 [Ion 数据类型](ql-reference.data-types.md)创建索引，其中包括 `list` 和 `struct`。但是，无论 Ion 类型如何，您都只能通过整个 Ion 值进行索引查找。例如，使用 `list` 类型作为索引时，不能按列表中的一个项目进行索引查找。
+ 只有使用相等谓词时，查询性能才会得到改善；例如`WHERE indexedField = 123` 或 `WHERE indexedField IN (456, 789)`。

  QLDB 不支持查询谓词不等式。因此，未实施范围过滤扫描。
+ 索引字段名称区分大小写，且最大长度可为 128 个字符。
+ 在 QLDB 中创建索引具有异步特点。非空表上完成索引所需的时间取决于表的大小。有关更多信息，请参阅 [管理索引](#working.manage-indexes)。

## 描述索引
<a name="working.manage-indexes.describe"></a>

在 QLDB 中创建索引具有异步特点。非空表上完成索引所需的时间取决于表的大小。要检查索引构建的状态，可以查询系统目录表[information\$1schema.user\$1tables](working.catalog.md)。

例如，以下语句在系统目录中查询 `VehicleRegistration` 表上的所有索引。

```
SELECT VALUE indexes
FROM information_schema.user_tables info, info.indexes indexes
WHERE info.name = 'VehicleRegistration'
```

```
{
    indexId: "Djg2nt0yIs2GY0T29Kud1z",
    expr: "[VIN]",
    status: "ONLINE"
},
{
    indexId: "4tPW3fUhaVhDinRgKRLhGU",
    expr: "[LicensePlateNumber]",
    status: "FAILED",
    message: "aws.ledger.errors.InvalidEntityError: Document contains multiple values for indexed field: LicensePlateNumber"
}
```

**索引字段数**
+ `indexId` – 索引的唯一 ID。
+ `expr` — 已编入索引的文档路径。该字段采用的字符串格式为：`[fieldName]`。
+ `status` — 索引的当前状态。索引的状态可以是以下值之一：
  + `BUILDING` — 正在积极为表建立索引。
  + `FINALIZING` — 已完成索引的构建并开始激活它以供使用。
  + `ONLINE` — 处于活动状态，可在查询中使用。在状态为在线之前，QLDB 不会在查询中使用该索引。
  + `FAILED`— 由于出现不可恢复的错误，无法建立索引。此状态的索引仍计入每个表的索引限额。有关更多信息，请参阅 [常见错误](#working.manage-indexes.errors)。
  + `DELETING` — 用户删除索引后正在主动删除索引。
+ `message` — 描述索引`FAILED`处于状态的原因的错误消息。仅在失败的索引中包含此字段。

### 使用 控制台
<a name="working.manage-indexes.describe.con"></a>

您也可以使用 AWS 管理控制台 来检查索引的状态。

**检查索引的状态（控制台）**

1. [登录并打开亚马逊 QLDB 控制台，网址为 /qldb。 AWS 管理控制台 https://console.aws.amazon.com](https://console.aws.amazon.com/qldb)

1. 在导航窗格中，选择**分类账**。

1. 在**分类帐**列表中，选择要管理其索引的分类帐名称。

1. 在分类账详细信息页面的**表格**选项卡下，选择要检查其索引的表名。

1. 在表格详细信息页面上，找到 **已编入索引的字段** 卡片。**索引状态** 列显示表中每个索引的当前状态。

## 删除索引
<a name="working.manage-indexes.drop"></a>

使用 [DROP INDEX](ql-reference.drop-index.md) 语句删除索引。删除索引时，该索引会从表中永久删除。

首先，从`information_schema.user_tables`中找到索引 ID。例如，以下查询返回`VehicleRegistration`表中已编入索引`LicensePlateNumber`字段的`indexId`。

```
SELECT indexes.indexId
FROM information_schema.user_tables info, info.indexes indexes
WHERE info.name = 'VehicleRegistration' and indexes.expr = '[LicensePlateNumber]'
```

然后，使用此 ID 删除索引。以下是取消表 ID `4tPW3fUhaVhDinRgKRLhGU`的示例。此时，索引 ID 是用双引号括起的唯一标识符。

```
DROP INDEX "4tPW3fUhaVhDinRgKRLhGU" ON VehicleRegistration WITH (purge = true)
```

**注意**  
该子句 `WITH (purge = true)` 是所有 `DROP INDEX` 语句所必需的，并且 `true` 是目前唯一支持的值。  
关键字`purge`区分大小写，并且必须为全小写。

### 使用 控制台
<a name="working.manage-indexes.drop.con"></a>

也可以使用 AWS 管理控制台 删除索引。

**删除索引（控制台）**

1. [登录并打开亚马逊 QLDB 控制台，网址为 /qldb。 AWS 管理控制台 https://console.aws.amazon.com](https://console.aws.amazon.com/qldb)

1. 在导航窗格中，选择**分类账**。

1. 在**分类帐**列表中，选择要管理其索引的分类帐名称。

1. 在分类账详细信息页面的**表格**选项卡下，选择要删除其索引的表名。

1. 在表格详细信息页面上，找到 **已编入索引的字段** 卡片。选择要删除的索引，然后选择 **删除索引**。

## 常见错误
<a name="working.manage-indexes.errors"></a>

本节介绍创建索引时可能遇到的常见错误，并建议可能的解决方案。

**注意**  
处于这种`FAILED`状态的索引仍计入每个表的索引限额。失败的索引还会阻止您修改或删除导致在表上创建索引失败的任何文档。  
您必须明确[删除](#working.manage-indexes.drop) 索引才能将其从限额中删除。

**文档包含索引字段的多个值:*fieldName*.**  
QLDB 无法为指定字段名建立索引，因为该表包含一个文档，该文档具有同一个字段的多个值（即重复的字段名）。  
必须先删除失败索引。然后，在重试创建索引前，请确保表中的所有文档的每个字段名只有一个值。您也可以为没有重复项的字段创建索引。  
如果您尝试插入的文档包含已在表格上编制索引字段的多个值，QLDB 也会返回此错误。

**已超过索引限制：表*tableName*已有*n*索引，无法创建更多索引。**  
QLDB 强制每个表最多只能包含五个索引，包括失败的索引。在创建新索引之前，必须要删除现有索引。

**未定义标识符为:的索引*indexId*。**  
您试图删除指定的表和索引 ID 组合中不包含的索引。若要了解如何检查现有索引，请参阅[描述索引](#working.manage-indexes.describe)。