DynamoDB表结构设计指南:使用嵌套结构是否符合规范?
DynamoDB表结构设计与嵌套对象使用说明
这两个官方建议和开发者实践的说法并不冲突,核心判断标准是你的业务访问模式:
嵌套对象的适用边界
嵌套的list/map不是不能用,只有符合以下所有条件时才推荐使用:
- 每次查询父数据时,一定需要同时返回所有嵌套的子数据,没有单独查询某个子项的需求
- 嵌套子数据的总数有明确上限,不会无限增长:DynamoDB单条item最大为400KB,无限制新增子项很容易触发该限制
- 不需要基于子数据的属性做索引、过滤查询:DynamoDB二级索引仅支持顶层属性,无法直接索引嵌套list内的字段,也无法高效筛选list内的单个元素
举个实际场景:用户的常用收货地址(最多5个)、商品的规格参数(固定10个以内)这类附属信息,用嵌套存储完全合理。
禁止使用嵌套对象的场景
只要满足以下任意一条,就不要用嵌套结构:
- 子数据会持续新增,数量没有上限:比如用户的所有订单、评论记录,用嵌套存储很快会撑大item,不仅消耗更多读容量,还会触发400KB的上限
- 需要单独修改、删除、新增某个子项:嵌套结构下修改单个子项需要先读取整个list,修改后再全量写回,高并发场景下极易出现写冲突,性能也会大幅下降
- 需要基于子项的属性做查询、统计:比如要筛选所有金额大于100的订单,嵌套结构下只能把整个list拉到客户端过滤,浪费读容量,效率极低
合理的DynamoDB表设计核心原则
始终围绕业务访问模式设计,不要照搬关系型数据库的设计逻辑:
- 先梳理全量业务查询需求,明确每个查询的过滤条件、返回内容、访问频率,所有设计都为这些查询服务
- 遵循官方推荐的单表设计原则,将经常需要关联查询的数据放在同一张表中:如果符合嵌套适用条件就用嵌套,否则用「分区键+排序键」的层级结构存储,比如用用户ID作为分区键,
ORDER#<订单ID>作为排序键,把每个订单作为单独的item存在同一张表,既满足关联存储的要求,也支持灵活的单订单操作 - 尽量控制单item大小:DynamoDB读容量单位按4KB计算,超过4KB的item会按比例多消耗容量,长期下来成本会高出很多
结构示例判断
对照上面的标准即可判断你提供的结构是否合理:如果嵌套的子项是和父元素强绑定、不会单独访问、数量固定的附属属性,保留嵌套是正确的设计;如果子项是独立的业务实体,有单独查询、修改、新增的需求,建议调整为同表下的独立item,用排序键前缀做区分即可。
内容的提问来源于stack exchange,提问作者Franczyk Rafał
相关产品推荐
相关产品推荐

