在 DynamoDB 中为关系数据建模的示例
此示例介绍如何在 Amazon DynamoDB 中为关系数据建模。DynamoDB 表设计对应 关系建模 显示的关系订单条目架构,采用 相邻列表设计模式,这是在 DynamoDB 中表示关系数据结构的常见方式。
设计模式需要定义一组通常与关系架构各个表关联的实体类型。随后,使用复合(分区和排序)主键将实体项目添加到表。这些实体项目的分区键是唯一标识项目的属性,在所有项目上通常称为 PK
。排序键属性包含的属性值可以用于反向索引或全局二级索引,通常称为 SK
。
定义以下实体,支持关系订单条目架构。
-
HR-Employee - PK:EmployeeID,SK:Employee Name
-
HR-Region - PK:RegionID,SK:Region Name
-
HR-Country - PK:CountryId,SK:Country Name
-
HR-Location - PK:LocationID,SK:Country Name
-
HR-Job - PK:JobID,SK:Job Title
-
HR-Department - PK: DepartmentID, SK: DepartmentName
-
OE-Customer - PK:CustomerID,SK:AccountRepID
-
OE-Order - PK OrderID,SK:CustomerID
-
OE-Product - PK: ProductID, SK: Product Name
-
OE-Warehouse - PK: WarehouseID, SK: Region Name
将这些实体项目添加到表后,可以将边缘项目添加到实体项目分区,定义这些项目之间的关系。下表演示此步骤。
在此示例中,表的 Employee
、Order
和 Product
Entity
分区都具有额外边缘项目,这些项目包含指向表上其他实体项目的指针。接下来,定义几个全局二级索引 (GSI),支持之前定义的所有访问模式。实体项目不会对主键或排序键属性使用完全相同的值类型。只需要让主键和排序键属性在表上显示为插入。
一些实体使用正确名称,其他实体使用其他实体 ID 作为排序键值,可让同一个全局二级索引支持多种查询类型。此技术称为 GSI 重载,实际消除了对包含多种项目类型的表的 20 个全局二级索引的默认限制。在下图中显示为 GSI 1。
GSI 2 旨在支持一种十分常见的应用程序访问模式,获取表中所有具有特定状态的项目。对于项目不均匀分布可用状态的大型表,此访问模式将产生热门键,除非项目分布在多个逻辑分区,可以并行查询。此设计模式称为 write sharding
。
要对 GSI 2 实现此模式,应用程序将为每个 Order 项目添加 GSI 2 主键属性,其中填充一个 0–N 之间的随机数,除非有具体理由,否则通常可以采用下面的公式计算 N。
ItemsPerRCU = 4KB / AvgItemSize PartitionMaxReadRate = 3K * ItemsPerRCU N = MaxRequiredIO / PartitionMaxReadRate
例如,假设预计以下内容:
-
系统中将有最多 200 万个订单,5 年内将增至 300 万。
-
多达 20% 的订单将在任何给定时间处于 OPEN 状态。
-
订单记录的平均大小约为 100 字节,订单分区的三个
OrderItem
记录每个约 50 字节,平均订单实体大小为 250 字节。
对于此表,N 系数计算如下所示。
ItemsPerRCU = 4KB / 250B = 16 PartitionMaxReadRate = 3K * 16 = 48K N = (0.2 * 3M) / 48K = 13
在此情况下,需要在 GSI 2 的至少 13 个逻辑分区分布所有订单,确保读取所有具有 OPEN
状态的 Order
项目不会在物理存储层产生热门分区。可以填充允许数据集存在异常的数字。因此,使用 N = 15
的模型可能合适。如上所述,将 0–N 随机值添加到表上插入的每个 Order
和 OrderItem
记录的 GSI 2 PK 属性。
这种划分方式假定,需要收集所有 OPEN
发票的访问模式发生的频率相对较低,这样可以利用爆增容量满足请求。可以使用 State
和 Date Range
排序键条件查询以下全局二级索引,根据需要生成处于指定状态的部分或所有 Orders
。
在此示例中,项目随机分布在 15 个逻辑分区。此结构之所以适用,是因为访问模式需要检索大量项目。因此,不可能所有 15 个线程都返回空结果集,这可能代表容量浪费。查询始终使用 1 个读取容量单位 (RCU) 或 1 个写入容量单位 (WCU),即使未返回任何内容或未写入任何数据。
如果访问模式需要对返回稀疏结果集的全局二级索引执行高速查询,更好的做法是使用哈希算法分配项目,而不是随机模式。在此情况下,选择的属性可能在运行查询时已知,插入项目时将该属性哈希至 0-14 键空间,然后可从全局二级索引高效读取项目。
最后,您可以再次访问之前定义的访问模式。下面是将用于新的 DynamoDB 版本应用程序的访问模式和查询条件列表。
序列号 | 访问模式 | 查询条件 |
---|---|---|
1 |
按员工 ID 查找员工详细信息 |
表上的主键,ID="HR-EMPLOYEE" |
2 |
按员工姓名查询员工详细信息 |
使用 GSI-1,PK="Employee Name" |
3 |
仅获取员工的当前工作详细信息 |
表上的主键,PK=HR-EMPLOYEE-1,SK 以“JH”开头 |
4 |
为客户获取日期范围内的订单 |
对每个 StatusCode,使用 GSI-1,PK=CUSTOMER1,SK="STATUS-DATE" |
5 |
显示所有客户的日期范围内处于 OPEN(未结)状态的所有订单 |
使用 GSI-2,PK=范围 [0..N] 内并行查询,SK 介于 OPEN-Date1 与 OPEN-Date2 之间 |
6 |
最近聘用的所有员工 |
使用 GSI-1,PK="HR-CONFIDENTIAL',SK > date1 |
7 |
查找特定仓库中的所有员工 |
使用 GSI-1,PK=WAREHOUSE1 |
8 |
获取产品的所有订单项,包括仓库位置清单 |
使用 GSI-1,PK=PRODUCT1 |
9 |
通过客户代表获取客户 |
使用 GSI-1,PK=ACCOUNT-REP |
10 |
按客户代表和日期获取订单 |
对每个 StatusCode,使用 GSI-1,PK=ACCOUNT-REP,SK="STATUS-DATE" |
11 |
获取具有特定职衔的所有员工 |
使用 GSI-1,PK=JOBTITLE |
12 |
按产品和仓库获取清单 |
表上的主键,PK=OE-PRODUCT1,SK=PRODUCT1 |
13 |
获取总产品清单 |
表上的主键,PK=OE-PRODUCT1,SK=PRODUCT1 |
14 |
获取按订单总计和销售周期排名的客户代表 |
使用 GSI-1,PK=YYYY-Q1,scanIndexForward=False |