DynamoDB单表设计优化咨询:减少冗余与GSI应用探讨
DynamoDB单表设计:冗余优化与访问模式适配方案
一、GSI确实可以减少冗余
你的思路是对的——用GSI替代主表中的冗余条目完全可行。当前设计里以TECH#tech_type为PK的条目如果是重复存储的发票副本,完全可以把这些冗余数据砍掉,改用GSI来支撑多维度查询。
核心逻辑是:主表只存一份完整的发票数据,把tech_type、proj_type作为发票的属性字段,然后通过GSI把这些属性映射为可查询的索引键,避免重复存储整份发票。
二、推荐的布局方案(适配你的三类访问模式)
方案1:主表仅存发票条目,GSI支撑多维度查询
这就是你提到的思路,具体落地:
- 主表结构:
- PK:
INVOICE#<invoice_id> - SK:
DETAILS(固定值,用于标识发票核心详情条目) - 属性:包含
tech_type、proj_type、invoice_amount、invoice_date等所有发票业务字段
- PK:
- GSI1(适配访问模式2:按技术类型查发票):
- GSI1-PK:
TECH#<tech_type> - GSI1-SK:
INVOICE#<invoice_id> - 投影策略:选择查询时需要的发票属性(比如只投影
invoice_id、invoice_amount),或用全投影(简单但略占存储)
- GSI1-PK:
- GSI2(适配访问模式3:按技术+类型组合查询):
如果你的访问模式3是“查询某技术类型下某项目类型的所有发票”,可以这么设计:- GSI2-PK:
TECH#<tech_type> - GSI2-SK:
TYPE#<proj_type>#INVOICE#<invoice_id>
查询时用PK=TECH#X且SK begins_with(TYPE#Y)就能快速筛选出目标发票;如果需要单独按项目类型查询,也可以把GSI2的PK设为TYPE#<proj_type>,SK设为TECH#<tech_type>#INVOICE#<invoice_id>,根据实际需求调整。
- GSI2-PK:
这个方案的优势是彻底消除主表冗余,所有发票数据只存一份,GSI按需投影,存储效率更高。唯一要注意的是GSI是最终一致性,如果你的业务对查询实时性要求极高(比如秒级内必须看到最新数据),可能需要权衡,但绝大多数业务场景都能接受。
方案2:主表保留轻量索引条目(强一致查询需求)
如果你的业务必须要求强一致查询(不能接受GSI的最终一致延迟),可以保留主表的多条目,但优化冗余程度——只存索引关联信息,不存完整发票副本:
- 发票主条目:
PK=INVOICE#<invoice_id>, SK=DETAILS,存完整发票数据; - 技术索引条目:
PK=TECH#<tech_type>, SK=INVOICE#<invoice_id>,仅存invoice_id和proj_type等必要关联字段,不存发票金额、日期等详情; - 类型索引条目:
PK=TECH#<tech_type>, SK=TYPE#<proj_type>#INVOICE#<invoice_id>,同样只存关联ID和必要分类字段。
查询时,先通过索引条目拿到invoice_id,再去主表查询完整发票数据。这种方案的冗余量很小(只有索引条目,没有完整发票副本),同时支持主表的强一致查询。
三、决策参考要点
- 一致性要求:强一致选方案2,最终一致选方案1;
- 查询灵活性:如果需要按项目类型跨技术查询,可以调整GSI的PK为
TYPE#<proj_type>; - 成本权衡:方案1存储成本更低,方案2写入次数更多(每次创建发票要写3条主表条目)但查询一致性更强。
内容的提问来源于stack exchange,提问作者Yolo_chicken
相关产品推荐
相关产品推荐

