核心观点
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 应用。
内容与图片版权归原作者所有 · 原文: https://dev.to/abhijeet_chaudhari_a/dynamodb-gsi-lsi-and-related-design-ideas-3fll