核心观点

1. DynamoDB 表设计应围绕访问模式,先确定应用如何查询再设计主键,避免全表扫描。

2. GSI 提供独立于基表的分区键和排序键,适合跨分区查询;LSI 共享基表分区键,仅改变排序键,适合同一分区内多维度查询。

3. 稀疏索引只包含具有特定属性的条目,可用于高效管理可选数据(如软删除),避免索引膨胀。

4. 查询(Query)基于键值高效检索,扫描(Scan)逐条读取全表,成本随数据量线性增长,应优先使用查询。

5. 热分区可通过复合分区键(如 customerId#region)或加随机后缀分散流量,自适应容量和自动缩放仅临时缓解,不能替代合理设计。

内容精讲

DynamoDB 的设计哲学是"先想查询,再定表结构"。在创建表之前,必须明确应用会提出哪些查询、哪些字段用于过滤和排序、哪些操作必须快速廉价、哪些数据可以归档。GSI(全局二级索引)正是为满足不同访问模式而生的工具:它允许使用与基表完全不同的分区键和排序键,DynamoDB 会为 GSI 维护独立的索引结构,包含所选属性、GSI 主键和指向基表项的指针。例如,订单表按订单 ID 存储,但经常需要按客户 ID 和日期查询,此时 GSI 就能提供替代查询路径

。GSI 适用于用户按邮箱查找、产品按类别查找等场景,能避免全表扫描,但写入时需同时更新基表和索引,开销更大

LSI(本地二级索引)则与基表共享分区键,只提供不同的排序键。当查询始终围绕同一分区键(如按客户 ID 查询所有订单),但需要按不同维度(如日期、状态)排序时,LSI 是更经济的选择。LSI 构建在基表同一分区内,不跨分区,因此写入开销低于 GSI。例如,基表以客户 ID 为分区键、订单日期为排序键,若想在同一客户分区内按订单状态查询,LSI 即可实现

。LSI 的局限性在于必须使用与基表相同的分区键,灵活性不如 GSI,但非常适合与同一分区键强关联的访问模式

稀疏索引是一种高效管理可选数据的技巧。如果只在部分项中存在某个属性(如 deletedAt 时间戳),对该属性建立 GSI 时,没有该属性的项不会出现在索引中。这样索引只包含有值的项,存储和写入成本大幅降低。例如,对 deletedAt 字段建索引,只有被软删除的项才会进入索引,查询未删除项时无需扫描全表

。稀疏索引不是全表扫描,而是有条件的索引,是建模可选数据的强大工具。

DynamoDB 提供两种读取操作:Query 和 Scan。Query 基于主键和排序键精确读取指定项,速度快、成本低;Scan 则读取全表或大部分数据,速度慢、成本随表大小线性增长。应始终优先使用 Query,仅在需要全表审查或生成报表时才用 Scan

。一个 Scan 在表增长后可能变得极其昂贵,设计时必须避免。

热分区是当大量请求集中到同一个分区键时产生的瓶颈。例如,所有请求都使用同一个用户 ID 作为分区键,该分区就会过载。缓解方法包括:使用更分散的分区键,如 customerId#region 或 customerId#randomSuffix,将流量分散到更多分区

。DynamoDB 自动将数据分区到内部存储分区,分区键是主要分布机制,良好设计的分区键能均匀分布数据和流量。

即使设计良好,也可能出现临时流量峰值。自适应容量允许 DynamoDB 在短时间内从其他未充分利用的分区借用容量,减少节流

。自动缩放则根据需求自动调整读写容量,适应长期变化。但这些功能只是辅助手段,不能替代良好的键设计——糟糕的分区键仍会导致热分区。

数据生命周期管理:TTL(生存时间)允许为项设置过期时间,到期后 DynamoDB 自动删除,适用于会话令牌、临时日志等

。PITR(时间点恢复)支持将表恢复到过去 35 天内任意时间点,防止误删或错误更新

。TTL 减少存储和清理工作,PITR 提供安全网,两者都是运维必备功能。

乐观锁定通过版本号防止并发写入丢失更新:更新前检查版本是否匹配,不匹配则失败重试。这是简单有效的并发控制手段。DynamoDB 设计的核心是模式思维——围绕访问模式建模,善用 GSI、LSI、稀疏索引、TTL 等工具,避免热分区和过度扫描等反模式。

阅读价值

适合使用 DynamoDB 的开发者、架构师,读完能掌握 GSI/LSI 选择策略、热分区避免方法,以及 DynamoDB 设计最佳实践,从而构建高性能、低成本的 NoSQL 应用。

阅读原文 → 返回 AI 技术文档

内容与图片版权归原作者所有 · 原文: https://dev.to/abhijeet_chaudhari_a/dynamodb-gsi-lsi-and-related-design-ideas-3fll