0Pricing
Cloud & IT Cert Prep · 课时

全局二级索引与本地二级索引

添加 GSI 和 LSI 以支持其他查询模式,而无需复制表。

全局二级索引与本地二级索引 是 CoddyKit 上的免费 Cloud & IT Cert Prep 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Cloud & IT Cert Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Cloud & IT Cert Prep 课程共包含 4 节课。

二级索引为何存在

DynamoDB 的主键定义了表中唯一高效的查询路径。如果您需要按照其他属性查询项目,例如在表的分区键为 CustomerId 时查找某个产品 ID 的所有订单,那么在没有二级索引的情况下,您必须执行开销很高的 Scan。

二级索引通过维护一份围绕不同键构建、自动更新的数据副本来解决这一问题。DynamoDB 提供两种类型:Global Secondary Indexes(GSI)和Local Secondary Indexes(LSI),二者各有不同的取舍。

Global Secondary Index(GSI)基础

Global Secondary Index允许您定义与基表完全不同的分区键(以及可选的排序键)。GSI 真正具有全局性,覆盖基表的所有分区。您可以通过查询 GSI,按照定义为 GSI 分区键的任意属性查找项目。

GSI 拥有独立于基表的预置吞吐量(或继承按需模式)。每个表最多可以创建 20 个 GSI,并且可以随时在现有表中添加或删除 GSI。

# Create a table with a GSI on ProductId
aws dynamodb create-table \
  --table-name Orders \
  --attribute-definitions \
    AttributeName=OrderId,AttributeType=S \
    AttributeName=ProductId,AttributeType=S \
    AttributeName=OrderDate,AttributeType=S \
  --key-schema AttributeName=OrderId,KeyType=HASH \
  --global-secondary-indexes '[
    {
      "IndexName": "ProductId-OrderDate-index",
      "KeySchema": [
        {"AttributeName": "ProductId", "KeyType": "HASH"},
        {"AttributeName": "OrderDate", "KeyType": "RANGE"}
      ],
      "Projection": {"ProjectionType": "ALL"},
      "ProvisionedThroughput": {"ReadCapacityUnits": 10, "WriteCapacityUnits": 5}
    }
  ]' \
  --provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5

Local Secondary Index(LSI)基础

Local Secondary Index与基表共享同一个分区键,但使用不同的排序键。LSI 之所以称为“本地”,是因为它只能在单个分区内查询(即查询具有相同分区键的项目)。因此,LSI 非常适合按照不同属性对某个客户的订单进行排序查询。

LSI 必须在创建表时定义,之后无法添加或删除。每个表最多可以有 5 个 LSI。LSI 共享基表的预置容量(没有独立的吞吐量),并且基表与 LSI 数据的组合受每个分区键 10 GB 存储限制的约束。

# Create a table with an LSI (at creation time only)
aws dynamodb create-table \
  --table-name Orders \
  --attribute-definitions \
    AttributeName=CustomerId,AttributeType=S \
    AttributeName=OrderDate,AttributeType=S \
    AttributeName=TotalAmount,AttributeType=N \
  --key-schema \
    AttributeName=CustomerId,KeyType=HASH \
    AttributeName=OrderDate,KeyType=RANGE \
  --local-secondary-indexes '[{
    "IndexName": "TotalAmount-index",
    "KeySchema": [
      {"AttributeName": "CustomerId", "KeyType": "HASH"},
      {"AttributeName": "TotalAmount", "KeyType": "RANGE"}
    ],
    "Projection": {"ProjectionType": "ALL"}
  }]' \
  --billing-mode PAY_PER_REQUEST

GSI 与 LSI:关键区别

以下是并列对比,便于备考时清晰理解:

  • 分区键:GSI 可以与基表不同;LSI 必须与基表相同
  • 排序键:两者都支持与基表不同的排序键
  • 创建时间:GSI 可随时创建;LSI 只能在创建表时创建
  • 吞吐量:GSI 拥有独立吞吐量;LSI 与基表共享吞吐量
  • 一致性:GSI 只能进行最终一致性读取;LSI 支持强一致性读取
  • 数量限制:最多 20 个 GSI;每个表最多 5 个 LSI

投影类型

创建索引时,您需要选择要投影(复制)到索引中的属性:

  • KEYS_ONLY:仅包含基表主键和索引键——索引最小,但获取非键属性时需要额外调用 GetItem
  • INCLUDE:包含键属性以及您指定的其他属性列表——在索引大小和访问模式之间取得平衡
  • ALL:将所有属性投影到索引中——最灵活,但存储和写入成本更高

请根据查询实际需要的属性选择投影类型。投影过多会在每次写入时浪费写容量单位;投影过少则会迫使您额外调用 GetItem,以获取索引中未包含的属性。

查询 GSI

查询 GSI 使用相同的 Query API,但需要指定 --index-name 参数。查询会针对 GSI 的键架构执行,而不是针对基表的键架构执行。GSI 查询始终具有最终一致性——GSI 会在基表写入后异步更新,因此会存在短暂延迟。

如果基表中的某个项目没有 GSI 的分区键属性,则该项目完全不会被包含在 GSI 中(稀疏索引模式)。这是一种只为部分项目建立索引的强大技术,例如,当 GSI 分区键为 Status 时,只索引状态为 PENDING 的所有订单。

# Query the GSI for all orders for a product in 2026
aws dynamodb query \
  --table-name Orders \
  --index-name ProductId-OrderDate-index \
  --key-condition-expression 'ProductId = :pid AND OrderDate BETWEEN :start AND :end' \
  --expression-attribute-values \
    '{":pid":{"S":"prod-abc"},":start":{"S":"2026-01-01"},":end":{"S":"2026-12-31"}}'

稀疏索引模式

稀疏索引利用了这样一个事实:只有包含 GSI 分区键值的项目,DynamoDB 才会将其投影到 GSI 中。将 GSI 分区键定义在只有部分项目拥有的属性上,即可创建一个仅包含该子集项目的索引。

例如,在 Orders 表中,只有尚未发货的订单具有 PendingShipmentDate 属性。针对 PendingShipmentDate 创建 GSI 后,该索引自然只包含尚未发货的订单,因此无需扫描整个表,就能高效查询所有待处理订单。

使用 GSI 过载实现写入分片

GSI 过载是一种高级单表设计技术:您可以将不同实体类型存储在同一个表中,并使用通用的 GSI 键属性(例如 GSI1PK 和 GSI1SK),根据项目类型采用不同的模式填充值。这样,每种实体类型都能通过同一个 GSI 获得高效的查询路径。

例如,对于 User 项目,设置 GSI1PK = 'COUNTRY#US' 和 GSI1SK = username;对于 Order 项目,设置 GSI1PK = 'STATUS#PENDING' 和 GSI1SK = orderDate。使用相应的前缀查询 GSI,即可高效检索目标实体类型。

索引限流与容量

GSI 的限流独立于基表发生。如果为 GSI 预配的写容量单位过低,那么写入会投影到 GSI 中的项目时就会被限流——即使基表仍有充足容量也是如此。请分别监控每个 GSI 的 ConsumedWriteCapacityUnits 和 ThrottledRequests。

一个常见问题是为 GSI 配置的容量低于基表,之后写入模式突然导致 GSI 的写入速率增加,从而发生限流。请对 GSI 使用 Auto Scaling,或选择按需模式来避免此问题。

何时使用 GSI、LSI,还是重新设计

SAA-C03 考试中的决策指南:

  • 需要按照完全不同的属性进行查询 → GSI
  • 需要在同一分区内进行查询,但使用不同的排序方式,并且在创建时就已确定 → LSI
  • 需要对备用排序键执行强一致性读取 → LSI(唯一选项,因为 GSI 只能提供最终一致性)
  • 存在 10 种或更多不同的查询模式 → 考虑采用带 GSI 过载的单表设计,而不是创建许多独立表
  • 只需要检索所有项目用于分析 → 重新考虑 DynamoDB 是否适合用作数据库

删除 GSI 与回填

您可以随时删除 GSI,而不会影响基表。向现有表添加新 GSI 时,DynamoDB 会通过扫描基表异步回填索引——对于大型表,这可能需要数分钟到数小时。回填期间,基表仍可完全进行读取和写入。

您可以在控制台中监控回填进度,也可以通过 DescribeTable API 检查索引的 IndexStatus 字段——回填期间该字段为 CREATING,完成后为 ACTIVE。在索引处于 ACTIVE 状态之前,请勿查询 GSI。

# Check GSI status during backfill
aws dynamodb describe-table \
  --table-name Orders \
  --query 'Table.GlobalSecondaryIndexes[*].{Name:IndexName,Status:IndexStatus}'

快速检查

请测试您对本课 AWS Solutions Architect(SAA-C03)概念的理解。

课程回顾

本课介绍了:GSI 提供备用分区键,并且可以随时添加;LSI 与基表共享分区键,并且必须在创建时定义;以及投影类型决定哪些属性会被复制到索引中。GSI 还支持稀疏索引和过载模式,从而提供更灵活的高级查询能力。接下来,我们将学习 DynamoDB 流和全局表。

常见问题解答

「全局二级索引与本地二级索引」课时是免费的吗?

是的 — 「全局二级索引与本地二级索引」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Cloud & IT Cert Prep 课程的其余内容,请升级到 CoddyKit PRO。 Cloud & IT Cert Prep 课程共包含 4 节课。

「全局二级索引与本地二级索引」这节课中我会学到什么?

添加 GSI 和 LSI 以支持其他查询模式,而无需复制表。 你通过在浏览器中直接运行的动手代码来练习 Cloud & IT Cert Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Cloud & IT Cert Prep 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Cloud & IT Cert Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「全局二级索引与本地二级索引」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Cloud & IT Cert Prep 课中编写并运行代码吗?

能。每节 Cloud & IT Cert Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 表、项目与主键
  2. 预置容量与按需容量
  3. 全局二级索引与本地二级索引
  4. DynamoDB Streams 与全局表
← 返回 Cloud & IT Cert Prep