在 DynamoDB 中的单个查询中获取父项和子项
Fetching parent and child item in single query in DynamoDB
我有以下一对多关系:
Account 1--* User
Account
包含可变的全局帐户级信息。
User
包含用户级别的信息,也是可变的。
当用户登录时,他们需要 Account
和 User
信息。 (我现在只知道UserId
)。
理想情况下,我希望将模式设计为需要单个查询。但是,如果不将 Account
复制到每个 User
中,我无法确定如何执行此操作,因此需要一些后台 Lambda 作业来传播对所有 User
对象的 Account
属性的更改 - - 作为记录,这似乎比简单地规范化数据和在每次登录时有 2 个查询更多的资源使用(和代码维护):获取用户,然后获取帐户(在用户对象中使用 FK 来标识帐户)。
是否可以设计一种架构,允许一个查询同时获取 和 并且不需要非事务性后台作业来传播更新? (事务性批量更新是不可能的,因为有 >25 个用户。)如果不是,那么 2 查询的想法是最好的/可接受的方法吗?
我将重点关注您问题的一个角度 - 2 次查询的想法。在许多情况下,它确实是一种 acceptable 方法,比其他方法更好。事实上,在许多 NoSQL 用途中,每个用户可见的请求都会导致明显超过两个数据库请求。事实上,人们经常说这就是 NoSQL 系统关心低尾延迟的原因(即,即使是 99% 的延迟也应该很低)。
您没有说明为什么要避免 2 查询解决方案。您提供的 2 查询实现有两个缺点:
- 成本更高:您需要进行两次查询而不是一次查询,成本(当读取小于 4 KB 时)是单次读取的两倍。
- 如果您需要执行第一个查询,然后才能执行第二个查询,则延迟会加倍。
根据您的用例的更多详细信息,您可能可以使用一些技巧来解决这两个问题:
对于延迟:您没有在您的应用程序中说明什么是“用户 ID”。如果它是某种唯一的数字标识符,也许可以将其设置为可以直接从用户 ID 确定帐户 ID,而无需 table 查找(例如,用户 ID 的第一位是帐户ID)。如果是这种情况,您可以同时启动两个查找,而不是将延迟加倍。成本仍然会翻倍,但延迟不会。
对于成本:如果每个帐户有大量用户(你说有超过 25 个 - 我不知道是不是更多),缓存帐户数据可能会有用,因此并非每个用户查找都需要再次读取帐户数据 - 它可能经常被缓存。如果帐户信息很少更改并且它的一致性不是什么大问题(我不知道它是否...),您还可以通过对帐户信息进行“最终一致性”读取来获得 - 这花费了一半常规的“一致”读取。
我有以下一对多关系:
Account 1--* User
Account
包含可变的全局帐户级信息。
User
包含用户级别的信息,也是可变的。
当用户登录时,他们需要 Account
和 User
信息。 (我现在只知道UserId
)。
理想情况下,我希望将模式设计为需要单个查询。但是,如果不将 Account
复制到每个 User
中,我无法确定如何执行此操作,因此需要一些后台 Lambda 作业来传播对所有 User
对象的 Account
属性的更改 - - 作为记录,这似乎比简单地规范化数据和在每次登录时有 2 个查询更多的资源使用(和代码维护):获取用户,然后获取帐户(在用户对象中使用 FK 来标识帐户)。
是否可以设计一种架构,允许一个查询同时获取 和 并且不需要非事务性后台作业来传播更新? (事务性批量更新是不可能的,因为有 >25 个用户。)如果不是,那么 2 查询的想法是最好的/可接受的方法吗?
我将重点关注您问题的一个角度 - 2 次查询的想法。在许多情况下,它确实是一种 acceptable 方法,比其他方法更好。事实上,在许多 NoSQL 用途中,每个用户可见的请求都会导致明显超过两个数据库请求。事实上,人们经常说这就是 NoSQL 系统关心低尾延迟的原因(即,即使是 99% 的延迟也应该很低)。
您没有说明为什么要避免 2 查询解决方案。您提供的 2 查询实现有两个缺点:
- 成本更高:您需要进行两次查询而不是一次查询,成本(当读取小于 4 KB 时)是单次读取的两倍。
- 如果您需要执行第一个查询,然后才能执行第二个查询,则延迟会加倍。
根据您的用例的更多详细信息,您可能可以使用一些技巧来解决这两个问题:
对于延迟:您没有在您的应用程序中说明什么是“用户 ID”。如果它是某种唯一的数字标识符,也许可以将其设置为可以直接从用户 ID 确定帐户 ID,而无需 table 查找(例如,用户 ID 的第一位是帐户ID)。如果是这种情况,您可以同时启动两个查找,而不是将延迟加倍。成本仍然会翻倍,但延迟不会。
对于成本:如果每个帐户有大量用户(你说有超过 25 个 - 我不知道是不是更多),缓存帐户数据可能会有用,因此并非每个用户查找都需要再次读取帐户数据 - 它可能经常被缓存。如果帐户信息很少更改并且它的一致性不是什么大问题(我不知道它是否...),您还可以通过对帐户信息进行“最终一致性”读取来获得 - 这花费了一半常规的“一致”读取。