【发布时间】: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 调用来完成),在非规范化示例中,我需要对所有锻炼执行昂贵的查询才能找到Exercises 和 exerciseTypeID == '4xBT',因为我无法将嵌套的 workoutTypeID 投影到全局二级索引中,因为它不是顶级属性。
我想这不会是一个特别极端或不寻常的场景 - 我是否错过了一种明显/简单的查询嵌套对象的方法,可以让我坚持使用非规范化架构?如果不是,我如何在非常频繁的稍微昂贵的数据库查询(2 个查询与 1 个查询)与大部分时间非常频繁的非常高效的查询和 10% 的时间非常慢的查询之间进行权衡?
【问题讨论】:
-
@H O 你解决过这个问题吗?
-
不,我最终使用了另一个似乎更适合该任务的 DB (mongodb),因为这种查询在应用程序中非常常见。
标签: database mongodb nosql amazon-dynamodb database-schema