【问题标题】:Using a table purely for its function as an index to facilitate searches使用表纯粹是因为它的功能是作为索引以方便搜索
【发布时间】:2011-09-05 10:58:41
【问题描述】:

我正在编写一个应用程序来对在线扑克手牌进行分析。我代表一张数字为 1-52 的扑克牌。我这样做的方式可以让我轻松提取卡片的花色和面额。

我正在使用 Java 编写并使用 MySQL 作为数据库。

下面描述了我面临的问题的一个示例。

我将持有超过 100 万手牌,每手牌最多有 10 名玩家,每手牌开始时都有两张牌。

因此仅就起始卡而言,可能存储了 2000 万个值。我需要做以下事情:

  • 找出其中一名玩家持有特定牌(比如红桃七)的每一手牌
  • 识别玩家持有的两张牌属于特定系列的每一手牌(例如同花连牌、同花牌、至少一张 A 等)。

我认为正确的做法如下:

  1. 我将有一个表(表 A),它存储游戏中玩家详细信息的详细信息。每位玩家每手一排。
  2. 要为给定玩家定义两张底牌,我将与表 A 与表(表 B)建立一对多关系,表的结构如下:
    • 在表 A 中有一个外键索引来定义与给定手牌和玩家对应的行
    • 表 A 中的每一行在表 B 中有两行,每张底牌对应一个。
    • 这样我可以在表 B 中搜索我要查找的牌,然后使用关系来查找出现牌的玩家和游戏。

所以这似乎是正确的,但我有效地将表 B 用作索引以方便搜索。

另一种方法是将起始卡片直接存储在表 A 中,作为两个字段,卡片 1 和卡片 2,每个字段都是整数。这样做的一个大问题是搜索会更加复杂,因为我总是必须将两张卡作为不同的字段进行专门检查。还要记住,底牌只是我需要存放卡片的一个地方。实际上,游戏中还有很多其他牌,我需要存储和搜索所有这些牌。这就是为什么我觉得我的方法可能是正确的,因为它已正确规范化。

我的方法有什么缺点吗?

【问题讨论】:

    标签: database-design


    【解决方案1】:

    enum 在这里看起来非常有效——数据基本上不会改变,除非你还打算玩塔罗牌(在 J 和 Q 之间有一个骑士)或拉米牌(每副牌增加 2-3 个小丑)。

    也就是说,对于卡片,我个人会坚持使用 int,因为您可以使用它来引入排序和 where 条件魔法。例如,如果您有:

    51 - AS
    50 - AH
    49 - AD
    48 - AC
    47 - KS
    ...
    01 - 2D
    00 - 2C
    

    可以肯定地说,(i mod 4) 产生卡片的花色(3 = S,2 = H 等),因此花色等级,而 i - (i mod 4) 与卡片编号相关,因此卡片秩。一些连接和(可能是功能性的)索引可以让您立即提取统计信息。

    这里的要点是,在内部,枚举与拥有 52 行表相同;只是a)您看不到数字的实际值,b)它们在实际查询发生之前在内部进行了预先评估(无论如何您都应该这样做)和c)您不能引入编号魔术,这可能否则对纸牌游戏很有用。

    【讨论】:

    • 非常感谢您对存储卡片的想法。这里有一些有用的想法。我主要关心的是构建数据库以便我可以执行大量查询,以及是否有任何理由要以非规范化的方式存储它们(card1、card2 在表的一行中。我认为判断根据您的回复,您的假设是我会将卡片存储在完全规范化的结构中,以便我可以进行“正确”查询。如果您能澄清一下,我将不胜感激。
    • 在阅读您的问题后,我的印象是,您已经或计划拥有某种表 (card_id, card),其行本质上是不可变的,并且(正确地)想知道它们是否可以替换为一个枚举。我会回答是的,它可以,但你最好探索将卡片表示为整数的想法。
    • 我想我会坚持我的建议。似乎 A 和 B 在任何一种情况下都可以合并...
    • 好的,感谢您抽出宝贵时间提供帮助。我承认我有点惊讶你认为 A 和 B 应该合并,因为这意味着去规范化并谴责我进行更复杂的查询来检查两个卡字段。欢迎您提出一些关于您为什么认为这是要走的路的想法。
    • 嗯,问题是我主要是 Postgres 迷。 PG 允许在函数调用上创建索引。使用代表两张牌的两个 int 字段,您可以索引 (card mod 4),用于花色,以及产生卡片等级所需的公式。您还可以创建部分索引,例如用对子索引手牌,或者用一个或多个 A 来索引手牌,等等。你最终会在一张精心构建的桌子上做所有的统计数据。
    【解决方案2】:

    我的背景是数据仓库设计,但这似乎很适合将数据存储在 52 位长的位结构中 - 如果包括其他游戏可能使用的两个小丑,则可能是 54 位。

    这将是一个通用结构,可以存储任意数量的起始牌,甚至可以存储新牌时游戏进程中的状态!

    你只需要决定你的例如您的 54 位结构将是 '1000100000....(很多位)....0000' 如果玩家有 Ace of Clubs 和 5 of Clubs,那么您可以使用位图从数据库中选择与您的匹配的行标准。如果您对西装进行了一些巧妙的分组,那么您可以获得一些非常快速的分析!

    如果空间是一个问题,位结构尤其重要。

    听起来是个有趣的项目!

    【讨论】:

    • 感谢您的回复。它对我的数据库问题没有帮助,但你对存储卡片的想法(以及丹尼斯的想法)让我停下来思考,因为我认为我可能会改进我目前的方法。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 2013-02-23
    • 2015-03-21
    • 2014-10-23
    相关资源
    最近更新 更多