多属性键模式
概述
通过多属性键,您可以创建全局二级索引(GSI)分区键和排序键,每个分区键和排序键最多由四个属性组成。这可减少客户端的代码数量,并简化了对数据进行初始建模和以后添加新访问模式的工作。
考虑一个常见的场景:要创建按多个分层属性查询项目的 GSI,传统上需要通过连接值来创建合成键。例如,在游戏应用程序中,如果要按锦标赛、地区和回合查询锦标赛比赛,您可以创建一个合成 GSI 分区键(例如 TOURNAMENT#WINTER2024#REGION#NA-EAST)和一个合成排序键(例如 ROUND#SEMIFINALS#BRACKET#UPPER)。这种方法是可行的,但是在写入数据时需要连接字符串,在读取时需要进行解析,如果要将 GSI 添加到现有表中,还需要在所有现有项目上回填合成键。这使得代码更加混乱,更难维护各个关键组件的类型安全。
多属性键可以解决 GSI 的这个问题。您可以使用多个现有属性(例如 tournamentId 和 region)来定义 GSI 分区键。DynamoDB 会自动处理复合键逻辑,将它们一起进行哈希处理用于数据分布。您使用域模型中的自然属性编写项目,而 GSI 会自动为它们编制索引。无需连接,无需解析,也无需回填。代码保持干净,数据保持类型化,查询保持简单。当您拥有使用自然属性分组的分层数据时(例如锦标赛 → 区域 → 回合,或企业 → 部门 → 团队),这种方法特别有用。
应用程序示例
本指南介绍如何为电子竞技平台构建锦标赛比赛跟踪系统。该平台需要有效地按多个维度查询比赛:按锦标赛和地区进行分组管理,按玩家查询比赛历史记录,按日期进行排程。
数据模型
在本演练中,锦标赛比赛跟踪系统支持三种主要访问模式,每种模式都需要不同的键结构:
访问模式 1:通过唯一 ID 查找特定比赛
-
解决方案:使用
matchId作为分区键的基表
访问模式 2:查询特定锦标赛和地区的所有比赛,可以选择按回合、分组或比赛进行筛选
-
解决方案:使用多属性分区键(
tournamentId+region)和多属性排序键(round+bracket+matchId)的全局二级索引 -
查询示例:“北美东部地区的所有 WINTER2024 比赛”或“北美东部地区 WINTER2024 上半区分组的所有半决赛”
访问模式 3:查询某个玩家的比赛历史记录,可以选择按日期范围或锦标赛回合进行筛选
-
解决方案:使用单分区键(
player1Id)和多属性排序键(matchDate+round)的全局二级索引 -
查询示例:“玩家 101 的所有比赛”或“玩家 101 在 2024 年 1 月的比赛”
通过查看项目结构,您可以清楚地看到传统方法与多属性方法之间的主要区别:
传统的全局二级索引方法(连接键):
// Manual concatenation required for GSI keys const item = { matchId: 'match-001', // Base table PK tournamentId: 'WINTER2024', region: 'NA-EAST', round: 'SEMIFINALS', bracket: 'UPPER', player1Id: '101', // Synthetic keys needed for GSI GSI_PK: `TOURNAMENT#${tournamentId}#REGION#${region}`, // Must concatenate GSI_SK: `${round}#${bracket}#${matchId}`, // Must concatenate // ... other attributes };
多属性全局二级索引方法(原生键):
// Use existing attributes directly - no concatenation needed const item = { matchId: 'match-001', // Base table PK tournamentId: 'WINTER2024', region: 'NA-EAST', round: 'SEMIFINALS', bracket: 'UPPER', player1Id: '101', matchDate: '2024-01-18', // No synthetic keys needed - GSI uses existing attributes directly // ... other attributes };
使用多属性键,您将具有自然领域属性的项目写入一次。DynamoDB 会自动将它们编入多个 GSI 的索引,而无需合成连接键。
基表架构:
-
分区键:
matchId(1 个属性)
全局二级索引架构(具有多属性键的 TournamentRegionIndex):
-
分区键:
tournamentId、region(2 个属性) -
排序键:
round、bracket、matchId(3 个属性)
全局二级索引架构(具有多属性键的 PlayerMatchHistoryIndex):
-
分区键:
player1Id(1 个属性) -
排序键:
matchDate、round(2 个属性)
基表:TournamentMatches
| matchId(PK) | tournamentId | region | round | bracket | player1Id | player2Id | matchDate | winner | 分数 |
|---|---|---|---|---|---|---|---|---|---|
| match-001 | WINTER2024 | NA-EAST | FINALS | CHAMPIONSHIP | 101 | 103 | 2024-01-20 | 101 | 3-1 |
| match-002 | WINTER2024 | NA-EAST | SEMIFINALS | UPPER | 101 | 105 | 2024-01-18 | 101 | 3-2 |
| match-003 | WINTER2024 | NA-EAST | SEMIFINALS | UPPER | 103 | 107 | 2024-01-18 | 103 | 3-0 |
| match-004 | WINTER2024 | NA-EAST | QUARTERFINALS | UPPER | 101 | 109 | 2024-01-15 | 101 | 3-1 |
| match-005 | WINTER2024 | NA-WEST | FINALS | CHAMPIONSHIP | 102 | 104 | 2024-01-20 | 102 | 3-2 |
| match-006 | WINTER2024 | NA-WEST | SEMIFINALS | UPPER | 102 | 106 | 2024-01-18 | 102 | 3-1 |
| match-007 | SPRING2024 | NA-EAST | QUARTERFINALS | UPPER | 101 | 108 | 2024-03-15 | 101 | 3-0 |
| match-008 | SPRING2024 | NA-EAST | QUARTERFINALS | LOWER | 103 | 110 | 2024-03-15 | 103 | 3-2 |
GSI:TournamentRegionIndex(多属性键)
| tournamentId(PK) | region(PK) | round(SK) | bracket(SK) | matchId(SK) | player1Id | player2Id | matchDate | winner | 分数 |
|---|---|---|---|---|---|---|---|---|---|
| WINTER2024 | NA-EAST | FINALS | CHAMPIONSHIP | match-001 | 101 | 103 | 2024-01-20 | 101 | 3-1 |
| WINTER2024 | NA-EAST | QUARTERFINALS | UPPER | match-004 | 101 | 109 | 2024-01-15 | 101 | 3-1 |
| WINTER2024 | NA-EAST | SEMIFINALS | UPPER | match-002 | 101 | 105 | 2024-01-18 | 101 | 3-2 |
| WINTER2024 | NA-EAST | SEMIFINALS | UPPER | match-003 | 103 | 107 | 2024-01-18 | 103 | 3-0 |
| WINTER2024 | NA-WEST | FINALS | CHAMPIONSHIP | match-005 | 102 | 104 | 2024-01-20 | 102 | 3-2 |
| WINTER2024 | NA-WEST | SEMIFINALS | UPPER | match-006 | 102 | 106 | 2024-01-18 | 102 | 3-1 |
| SPRING2024 | NA-EAST | QUARTERFINALS | LOWER | match-008 | 103 | 110 | 2024-03-15 | 103 | 3-2 |
| SPRING2024 | NA-EAST | QUARTERFINALS | UPPER | match-007 | 101 | 108 | 2024-03-15 | 101 | 3-0 |
GSI:PlayerMatchHistoryIndex(多属性键)
| player1Id(PK) | matchDate(SK) | round(SK) | tournamentId | region | bracket | matchId | player2Id | winner | 分数 |
|---|---|---|---|---|---|---|---|---|---|
| 101 | 2024-01-15 | QUARTERFINALS | WINTER2024 | NA-EAST | UPPER | match-004 | 109 | 101 | 3-1 |
| 101 | 2024-01-18 | SEMIFINALS | WINTER2024 | NA-EAST | UPPER | match-002 | 105 | 101 | 3-2 |
| 101 | 2024-01-20 | FINALS | WINTER2024 | NA-EAST | CHAMPIONSHIP | match-001 | 103 | 101 | 3-1 |
| 101 | 2024-03-15 | QUARTERFINALS | SPRING2024 | NA-EAST | UPPER | match-007 | 108 | 101 | 3-0 |
| 102 | 2024-01-18 | SEMIFINALS | WINTER2024 | NA-WEST | UPPER | match-006 | 106 | 102 | 3-1 |
| 102 | 2024-01-20 | FINALS | WINTER2024 | NA-WEST | CHAMPIONSHIP | match-005 | 104 | 102 | 3-2 |
| 103 | 2024-01-18 | SEMIFINALS | WINTER2024 | NA-EAST | UPPER | match-003 | 107 | 103 | 3-0 |
| 103 | 2024-03-15 | QUARTERFINALS | SPRING2024 | NA-EAST | LOWER | match-008 | 110 | 103 | 3-2 |
先决条件
在开始之前,请确保您满足以下条件: