DynamoDB 单表设计的优势与考量

大多数开发都有关系数据库设计经验,在初次使用 DynamoDB 设计数据模型的时候,很容易陷入关系数据库的思维陷阱, 不自觉的遵守关系数据库设计的范式, 尝试将数据模型规范化,每个实体或实体关系都有对应的单独的表,通常称之为多表设计。
与之对应的是,将所有实体和实体关系都存储在同一张表中,毕竟 DynamoDB 是 Schemaless 的数据库,称之为单表设计。
这儿要强调的是,这两种设计只是极端的两点。可能也不是一个合适的命名,因为在实际应用中,单表设计并不意味着只能有一张表。
在两个极端之间,单表设计更倾向于将相关实体存入在同一张表中,多表设计则倾向将不同实体类型存入不同的表中。

官方文档中,单表和多表设计比较时也较为推荐单表设计。本文就来根据实际经验,讨论下实际实践中单表设计的优势。
我们自己的项目采用的是单表设计,很大程度上受 《The DynamoDB Book》影响,作者 Alex DeBrie 是单表设计的推崇者。当然,我们项目中已经有十几张表,尽管我们已经尽量将相关实体存入同一张表中。

单表设计优点

1. 多个不同类型实体只需要一个请求

这个是单表设计的最大卖点,可以在一个请求中获取多个不同类型的实体,减少了请求次数,提高性能并降低成本。
《The DynamoDB Book》书中举的例子是用户信息和用户订单信息,如果是多表设计,用户信息表和用户订单表必须分别查询,而单表设计只需要一次查询。
在下面表,用户信息和订单信息使用相同的 Partition Key,在同一个 itemCollection 中,可以在一个 Query 请求中同时获取用户信息和订单信息。
single-table.png

实际应用中的问题:上层的应用往往并不关心底层实现,很显然这两个不同的实体,在上层对应这不同的功能方法。更不用说,可能会有至少五六种不同的实体类型在同一个 itemCollection 中,除非刻意设计,否则很难利用到这条优点。
在 《The DynamoDB Book》中甚至刻意维护不同实体之间的顺序,以便更高效的查询。在实际应用中,我们根本不会关心同一个 itemCollection 中的实体类型的顺序,总的来说这个优点在实际应用中并不是很明显。

2. 降低账单成本和延时

两条记录总大小不超过 4KB 的单一请求是 0.5 RCU 一致性读
两次独立请求总大小不超过 4KB 是 1RCU 一致性读
两个独立数据的请求时间平均来说比单独的一次请求要长

账单的优点比较显而易见:减少了请求次数,自然减少了账单成本,通常单个实体记录不会很大,多个实体记录也不一定会有 4KB。
延时的优点也很容易理解,单次请求大多数情况下比两次请求要快。

问题是,即便在单表中,在实际应用中,上层服务并不知道下面的实现细节,还是会发出两个请求,这样这个点优点对我们来说一样并不存在。

3. 单表更容易管理

权限维护变少
容量管理更容易预测
监控更少的 Alarm
只需要在一张表上管理密钥

权限维护变少,同时带来的是权限粒度没有那么细,实际当中我们已经觉得我们的权限太细了,每个 Lambda 都配置不同的角色权限。
这些优点是实实在在的,单表设计更容易管理,不需要配置更多的配置,也不需要在每个 Lambda 中都添加对应表的访问权限。

4. 流量更顺滑

就像股票指数要比单一股票更稳定一样,单表设计的流量更稳定,更能充分利用 预置 功能。

单表设计的缺点

缺点不需要解释太多,主要是:

  1. 学习曲线陡峭
    在理解了 DynamoDB 的核心概念之后,单表设计思想不难理解,只是遵循这种设计是有一定的成本的,并不认为学习曲线很陡峭。
  2. 同一张表中不同实体类型的数据需求(备份,加密)必须一致
  3. 所有的数据变更都会影响到 Streams
  4. 使用 GraphQL 更难实现
  5. 高级 SDK 比如 DynamoDBMapper 很难处理结果因为不同实体对应不同类

总结

总的来说,DynamoDB 的设计比较灵活,很多需求都可以满足,单表和多表之间也没有绝对的界限。
即便是单表的推崇者也只是推荐一张表对应一个服务,而不是整个项目只有一张表。
个人认为强调单表设计更多的是一种功矫枉过正,尝试让大家摆脱关系数据库的思维惯性。
在实际应用中,个人建议是无论如何先需要学习和理解 DynamoDB 的核心概念,然后根据实际需求来权衡单表和多表设计。

相关文章推荐:

  1. Single-table vs. multi-table design in Amazon DynamoDB
  2. Single table design for DynamoDB: The reality
  3. The What, Why, and When of Single-Table Design with DynamoDB

评论