GSI 与 LSI
二级索引、查询模式。
35 分钟
GSI 与 LSI
主键外的查询需求靠 二级索引 解决:GSI(Global Secondary Index) 独立分区键,跨表投影;LSI(Local Secondary Index) 同 PK、不同 SK,创建表时固定。
学习目标
- 区分 GSI 与 LSI 的适用场景
- 理解投影类型(KEYS_ONLY / INCLUDE / ALL)
- 为「按课时查进度」设计 GSI
核心内容
GSI vs LSI
| GSI | LSI | |
|---|---|---|
| PK | 可与基表不同 | 必须与基表相同 |
| 创建时机 | 随时添加 | 仅建表时 |
| 容量 | 独立 RCU/WCU | 共享基表分区 |
| 数量 | 每表 20 个 | 每表 5 个 |
# 创建 GSI:按课时 slug 反查用户进度
aws dynamodb update-table \
--table-name UserProgress \
--attribute-definitions \
AttributeName=GSI1PK,AttributeType=S \
AttributeName=GSI1SK,AttributeType=S \
--global-secondary-index-updates '[{
"Create": {
"IndexName": "ByLesson",
"KeySchema": [
{"AttributeName": "GSI1PK", "KeyType": "HASH"},
{"AttributeName": "GSI1SK", "KeyType": "RANGE"}
],
"Projection": {"ProjectionType": "ALL"},
"ProvisionedThroughput": {"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}
}
}]'
On-Demand 模式可省略 ProvisionedThroughput(见 ddb-capacity)。
写入时维护 GSI 键
{
"PK": "USER#u_1001",
"SK": "LESSON#ddb-crud",
"GSI1PK": "LESSON#ddb-crud",
"GSI1SK": "USER#u_1001",
"action": "complete"
}
Query GSI1PK = LESSON#ddb-crud → 该课所有用户进度。MySQL 等价:INDEX(lesson_slug) + WHERE lesson_slug = ?(sql-essentials)。
设计原则
- 一个访问模式一个索引,避免「万能 GSI」
- 投影
INCLUDE只带必要字段,降低存储与写入放大 - GSI 写入与基表 最终一致(通常毫秒级延迟)
对照 mongodb-essentials:MongoDB 任意字段建索引即可查;DynamoDB 需 预定义 索引键并随 Item 写入。
练习
- 为 UserProgress 设计
ByTrackGSI(按 trackSlug 查进度)