如何在数据库中表示一系列动作,同时保留每个动作的详细信息?
Posted
技术标签:
【中文标题】如何在数据库中表示一系列动作,同时保留每个动作的详细信息?【英文标题】:How to represent a sequence of actions in a database while keeping detailed information about each action? 【发布时间】:2020-04-23 21:55:37 【问题描述】:我们有很多玩家可以在游戏中采取的行动。想象一下纸牌游戏(如扑克)或棋盘游戏,其中每个决策点都有多种选择,并且有明确的事件顺序。我们跟踪玩家采取的每一个动作。我们关心行动的规模(如果适用)、未采取的其他行动可能性、采取行动的玩家、玩家在行动前面临的行动。此外,我们需要知道在我们正在查看的操作之前是否发生了某些操作。
数据库帮助我们回答以下问题: 1. 有机会采取行动 A 的频率如何? (sum(actionA)/sum(actionA_opp) 2. 有机会采取行动 A 和行动 B 发生的频率是多少? 3. 行动 A 多久采取一次大小为 X 的行动,或在 Y 秒内采取行动的频率,假设行动 B 发生而行动 C 没有发生? 4. 鉴于玩家 P 执行了动作 B,动作 A 多久执行一次?
因此,对于每个动作,我们需要保留有关采取该动作的玩家、大小、时间、执行的动作、可用的动作机会以及其他特征的信息。动作的数量是有限的。
一个游戏平均可以有 6 个动作,有些可以达到 15 个。 可能有数百万个游戏,我们希望所有游戏的聚合查询尽可能快地运行。 (秒)
它可以在文档数据库中表示为嵌入文档的数组,例如:
game: 123
actions: [
player: Player1,
action: deals,
time: 0.69,
deal_opp: 1
discard_opp: 1
,
player: Player2,
action: discards,
time: 1.21
deal_opp: 0,
discard_opp: 1,
...
]
或者在关系模型中:
game | player | seq_n | action | time | deal_opp | discard_opp
123 | Player | 1 | deals | 0.28 | 1 | 1
我想出的所有可能的设计都不能满足我的所有条件。 在呈现的关系模型中,要查看在同一游戏中采取的先前动作需要 N 个内部连接,其中 N 是我们要过滤的先前动作。鉴于该表将包含数十亿行,因此需要在十亿行表上进行多次自连接,这似乎非常低效。
如果我们将其存储在一个宽列表中,并在一行中表示整个序列,我们就有非常简单的聚合(可以通过比较列值来过滤发生的事情和没有发生的事情,例如 sum(deal)/sum( deal_opp),其中 deal_opp = 1 以在玩家有机会这样做的情况下获得交易动作的频率)但我们不知道谁采取了给定的动作,这是必要的。我们不能仅仅在一个动作旁边附加一个玩家列来表示谁采取了这个动作,因为像跟注或弃牌这样的动作或者可能有很多玩家连续(在扑克游戏中,一个玩家加注,1 个或多个玩家可以跟注)。
更多可能性:
图形数据库(考虑到我们最多有 1 个其他连接节点,这太过分了?- 基本上是一个链表) 关闭表(更有效地查询以前的操作) ??【问题讨论】:
“在呈现的关系模型中,要查看在同一个游戏中采取的先前动作需要 N 个内部连接”。这是不真实的。您可以根据数据库使用窗口函数或数组聚合。 你能举个例子,你将如何使用窗口函数来查看在具有相同 game_id 的游戏中的当前动作之前是否没有发生动作? 。 .不,你的问题实在是太宽泛了。如果您有特定问题,请将其作为新问题提出。 我很想将持久存储与任何快速分析分开。将传入事件流式传输到某个存储(例如 RDBMS)以进行中期工作,同时还将事件流式传输到任何分析包,并让他们为他们关心的特定指标集做任何有效的事情。许多统计数据可以“在线”计算,因此您无需进行任何全面扫描即可回答,例如你的第一个问题可以这样回答 【参考方案1】:如果我理解得很好,您是否正在处理如何在数据库中存储决策树。对 ? 我记得我在几年前编写了一个国际象棋游戏,这意味着每个动作都是两个用户先前动作的连续集合。因此,要记录所有操作以及您需要的所有详细信息,我认为您应该检查以下内容: + 在关系数据库中,最有效的存储树的方法是修改前序树遍历。不容易tbh,但你可以试一试。
这将对您有所帮助:https://gist.github.com/tmilos/f2f999b5839e2d42d751
【讨论】:
以上是关于如何在数据库中表示一系列动作,同时保留每个动作的详细信息?的主要内容,如果未能解决你的问题,请参考以下文章