You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DynamoDB表设计咨询:获取用户未作答的已发布问题

DynamoDB表设计方案:适配用户未作答题目查询与结果数据高增长场景

针对你的需求,结合DynamoDB的特性,以下是几种高效的表设计方案,重点解决QuestionResult数据快速增长下的查询性能问题:

方案一:单表设计(DynamoDB最佳实践)

DynamoDB单表设计通过合理的主键设计,避免跨表关联,提升整体读写效率,尤其适合多实体关联查询场景。

表结构定义

  • 分区键(PK):采用实体类型#ID格式,区分不同实体:
    • Question实体:QUESTION#<QuestionID>
    • User实体:USER#<UserID>
    • QuestionResult实体:USER_RESULT#<UserID>
  • 排序键(SK):用于实体内部的排序和区分:
    • Question实体:ORDER#<Order>(按题目顺序排序)
    • User实体:USER_DATA(固定值,标识用户数据)
    • QuestionResult实体:QUESTION#<QuestionID>(关联对应的题目ID)
  • 全局二级索引(GSI1):
    • 分区键:IS_PUBLISHED#<IsPublished>(如IS_PUBLISHED#true)
    • 排序键:ORDER#<Order>
    • 投影属性:PK(即QUESTION#<QuestionID>)

查询流程

  1. 获取用户已作答题目ID:
    执行Query操作,指定PK = 'USER_RESULT#<目标UserID>',SK前缀匹配QUESTION#,返回所有已作答的QuestionID集合(从PK中提取数字部分)。
  2. 获取未作答的已发布题目:
    查询GSI1,指定PK = 'IS_PUBLISHED#true',按SK升序排序,分页获取题目。在客户端过滤掉已在步骤1集合中的QuestionID,直到凑够10条。

优化点

  • 每次查询GSI1时多取5-10条数据(比如取15条),减少分页次数,提升过滤效率。
  • 利用DynamoDB的投影表达式,仅返回QuestionID和Order,减少数据传输量。

方案二:多表设计+针对性GSI

如果习惯分表管理实体,可采用以下设计,兼顾数据隔离和查询效率:

各表结构

  1. Questions表

    • 分区键(PK):QuestionID(int)
    • 属性:Order(int)、IsPublished(bool)、Data(JSON)
    • GSI1:
      • 分区键:IsPublished(bool)
      • 排序键:Order(int)
      • 投影属性:QuestionID
  2. Users表

    • 分区键(PK):UserID(int)
    • 属性:Data(JSON)、LastAccessedOrder(int,可选,用于优化查询)
  3. QuestionResults表

    • 分区键(PK):UserID(int)
    • 排序键(SK):QuestionID(int)
    • 属性:Result(JSON)

查询流程

  1. 获取用户已作答题目ID:
    执行Query操作,指定PK = <目标UserID>,返回所有SK(即QuestionID)组成的集合。
  2. 高效获取未作答题目:
    • 如果用户表有LastAccessedOrder属性,先查询GSI1,指定IsPublished = true且Order > <LastAccessedOrder>,按Order升序取15条,过滤掉已作答的题目,凑够10条后更新LastAccessedOrder为这批题目的最大Order。
    • 若上述结果不足10条,再查询Order <= <LastAccessedOrder>的已发布题目,过滤未作答的补充。

适配高增长场景的优势

  • QuestionResults表采用UserID作为PK、QuestionID作为SK,写入请求会均匀分布到不同分区,避免热点问题,支撑高并发写入。
  • GSI1的查询是高效的范围扫描,配合LastAccessedOrder可大幅减少需要过滤的数据量,尤其适合用户持续获取新题的场景。

关键注意事项

  • 避免全表扫描:所有查询必须基于主键或GSI,绝对禁止对QuestionResults表做全表扫描来过滤用户已答题。
  • 数据去重:写入QuestionResult时,使用条件表达式attribute_not_exists(QuestionID),确保每个用户对同一题目仅存一条结果。
  • 批量操作:如果需要批量检查题目是否已作答,可使用BatchGetItem操作,减少单次请求次数。

内容的提问来源于stack exchange,提问作者Mykyta Karpyshyn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 01:10:26