【问题标题】:Should a NoSQL (dynamodb) table be denormalized if data needs to be queried independently?如果需要独立查询数据,是否应该对 NoSQL (dynamodb) 表进行非规范化?
【发布时间】:2018-10-06 01:31:36
【问题描述】:

我有一个使用 AWS Lambda / API Gateway / Dynamodb 创建的简单 API,用于记录/查询锻炼及其相关锻炼。我希望我的问题同样适用于其他 NoSQL 数据库,例如MongoDB。

基本结构很简单:锻炼和锻炼之间存在一对多的关系,因此从 API 的角度来看,/workouts/{id} 将锻炼作为 JSON 对象返回,/workouts/{id}/exercises 返回属于的锻炼到锻炼。我还希望/exercises?exerciseTypeID={exerciseTypeID} 返回特定类型的所有练习,例如/exercises?exerciseTypeID=4xBT 应该返回所有跑步练习。

在 dynamodb 中构建这些数据时,我似乎有两种选择:通过在锻炼对象中嵌套练习来进行非规范化,如下所示:

锻炼(非规范化):

'id': '8977-9823-QbUU',
    'name': 'Marathon training',
    'date': '22-08-2015',
    'exercises': {
        '1112-0120-XaBt': {
            'name': 'Warmup',
            'exerciseTypeID': '4xBT', # Running
            'distance': '2500', # meters
            'speed': '9', # km/h
            'duration': 1000 # seconds
         },
         '2253-4288-TKhg': {
             'name': '10K practice',
             'exerciseTypeID': '4xBT', # Running
             'distance': '10000',
             'speed': '11',
             'duration': 3272 # seconds
         }

    }

}

或者,将架构标准化并将练习存储在单独的表中,通过workoutID 链接到锻炼,如下所示:

锻炼(标准化):

{
     'id': '8977-9823-QbUU',
     'name': 'Marathon training',
     'date': '22-08-2015'
}

练习(标准化):

{
     'id': '1112-0120-XaBt',
     'workoutID': '8977-9823-QbUU',
     'name': 'Warmup',
     'exerciseTypeID': '4xBT', # Running
     'distance': 2500, # meters
     'speed': 9, # km/h
     'duration': 1000 # seconds
}

{
     'id':  '2253-4288-TKhg',
     'workoutID': '8977-9823-QbUU',
     'name': '10K run',
     'exerciseTypeID': '4xBT', # Running
     'distance': 10000, # meters
     'speed': 11, # km/h
     'duration': 3272 # seconds
}

锻炼的主要查询是获取与特定锻炼相关的所有锻炼。在此基础上,按照第一个示例,我应该通过将锻炼数据存储在锻炼对象中来进行非规范化,这样我只需执行一次查询即可获取锻炼和所有相关锻炼。或者,如果我进行标准化,那么我需要在大多数情况下执行 2 次查询,因为需要在锻炼中查看锻炼直观地是一个非常常见的请求,即标准化对于这个用例来说效率较低。

复杂之处在于还需要独立于锻炼直接访问锻炼(可能是观看锻炼及其锻炼频率的 10%)。在非规范化模式中,这似乎会很慢/很昂贵。例如,如果我想了解我的跑步时间在过去 10 次跑步中的改善情况(我可以使用/exercises?exerciseTypeID={exerciseTypeID} API 调用来完成),在非规范化示例中,我需要对所有锻炼执行昂贵的查询才能找到ExercisesexerciseTypeID == '4xBT',因为我无法将嵌套的 workoutTypeID 投影到全局二级索引中,因为它不是顶级属性。

我想这不会是一个特别极端或不寻常的场景 - 我是否错过了一种明显/简单的查询嵌套对象的方法,可以让我坚持使用非规范化架构?如果不是,我如何在非常频繁的稍微昂贵的数据库查询(2 个查询与 1 个查询)与大部分时间非常频繁的非常高效的查询和 10% 的时间非常慢的查询之间进行权衡?

【问题讨论】:

  • @H O 你解决过这个问题吗?
  • 不,我最终使用了另一个似乎更适合该任务的 DB (mongodb),因为这种查询在应用程序中非常常见。

标签: database mongodb nosql amazon-dynamodb database-schema


【解决方案1】:

我的想法是复制数据。两者都做。存储相当便宜,因此只要您有一项服务来进行更新/添加,这会对两个表进行更改,这不会影响运行数据库的成本,并且应该会导致快速查询响应。我假设数据不会经常变化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-12
    • 2011-12-18
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 2015-01-28
    • 2015-09-09
    • 2016-10-15
    相关资源
    最近更新 更多