DynamoDB 中的 GSI 对比 LSI
全局二级索引(GSI)和局部二级索引(LSI)都能让你按一个并非表键的属性进行 Query。但它们不可互换 —— 这些差异决定了某个访问模式需要哪一种。
真正重要的差异
| GSI | LSI | |
|---|---|---|
| 分区键 | 任意属性 | 与表相同 |
| 排序键 | 任意属性 | 任意属性 |
| 何时创建 | 任何时候 | 仅在建表时 |
| 一致性 | 仅最终一致 | 可强一致 |
| 容量 | 独立拥有 | 与表共享 |
| 写入传播 | 异步(最终一致) | 同步(原子) |
| 每表上限 | 20(默认,可上调) | 5(硬性) |
| 10 GB 分区上限 | 无 | 有(每个 PK) |
一条经验法则
- 需要一个不同的分区键(例如按
status而非customer查找订单)?那你需要 GSI —— LSI 无法重新分区。 - 需要在同一分区内有第二种排序顺序 —— LSI 保留表完全相同的分区键,只换入一个不同的排序键 —— 且需要预先确定、配合强一致读取?那 LSI 更合适。
这个选择归结为一个问题 —— 你要改的是哪个键:
不同的分区键就只能用 GSI;唯一适合 LSI 的情形,是在同一分区上使用不同的排序键。
实际上,大多数团队几乎只用 GSI:它们可以事后添加、独立扩容,且不受 10 GB 每分区上限的约束。可以重载单个 GSI 的键来服务多个模式 —— 参见单表设计。
如果你添加 GSI 是为了消除某个 Scan,请记住它有自己独立的读/写容量。用定价计算器估算这笔额外成本,并试用 DynoTable 在决定采用某个索引之前先查看它的投影属性。