【问题标题】:What is the most efficient way to organise these tables + rows? - MySQL组织这些表+行的最有效方法是什么? - MySQL
【发布时间】:2012-07-25 15:47:56
【问题描述】:

我将在我的网站上运行彩票,因此需要有一个地方来存储彩票和号码。我肯定会有一个名为tickets 的表,其中每一行都有自己的票号、相关联的彩票ID 和所有其他信息(例如所属用户的ID)。

但是,我的问题是我是否应该在tickets 中创建另一个字段来保存票证上选择的数字。不能创建多个字段,例如number1number2 等,因为每个彩票都会有不同类型的彩票(即lottery1 可能会要求您选择 4 个号码,lottery2 可能会要求您选择6).

所以我可以创建一个 VARCHAR 或 TEXT 的新字段来接受逗号分隔的票号,即:1,2,3,4,5,6 或创建另一个名为 numbers 的新表,其中每一行都会关联票号和票号用它。但是我不确定这种方法是否非常有效,对于一张 6 个号码的票,tickets 表中需要 1 行,numbers 表中需要 6 行。

这些选项中哪个最有效?或者有比这更好的方法吗?请记住,在抽奖结束时,代码将需要循环检查每张彩票是否中奖 - 所以选项 2 可能过于占用资源。

【问题讨论】:

  • 数字“是”一张票的属性,不是吗?在这种情况下,将其作为票证的一部分。使用简单的 CSV 或 DSV 不应自动被视为非规范化,因为号码本身是一个实体,就像 SSN 或电话号码一样。如果乐透号码存储在min,..,max,则可以使用简单的正则等式和索引。对于“子乐透号码”查询,例如“包含数字 N 的票”,那么这是另一个用例/问题..
  • 在我看来,CSV 方法似乎是最有效和最简单的,因为您只需 explode() 获取数据即可。
  • 为了它的价值,小心您将在当地的法律中进行您的彩票。
  • .. 行数并不是真正的问题(SQL 数据库可以很好地跨行扩展),但听起来问题过于复杂。我强烈建议将数字视为实体。
  • 在这种情况下我将如何使用索引?虽然没有一个会员可以购买多张相同的票,但同一张票可以由多个会员购买。

标签: php mysql database-design rows database-performance


【解决方案1】:

我会使用第二个选项来创建新表,称为数字,并且您有与之关联的数字。

但我还要在门票表中添加一个字段,在其中指示可以选择的号码数量,以及检查是否使用该门票插入的号码数量的条件(在查询中使用 COUNT)小于可以选择的数字数量,然后插入。

【讨论】:

    【解决方案2】:

    在下文中,“Ticket[Number]”应理解为“选定的彩票号码”。请记住,Set(a,b,c) 等于 Set(c,b,a)


    我会这样:

    Purchase
      -PersonID // associate Person (one person can have many purchases)
      -TicketID // associate Ticket (a purchase is for one "ticket",
                //                   which can be purchased many times)
      -DisplayTicketNumber // for Human Display
    
    Ticket
      -TicketNumber
    

    Purchase:M-1:Ticket

    DisplayTicketNumber 是用户选择的数字,例如“3,1,2”,而另一方面,TicketNumber 是规范化的票号,其中小值放在首位。因此,最终形式为min,..,max 或类似形式。也就是说,具有相同值集(以任何顺序)的任意数量的DisplayTicketNumbers 将具有相同的TicketNumber

    DisplayTicketNumber  TicketNumber
    1,2,3                1,2,3
    2,3,1                1,2,3
    3,2,1                1,2,3
    3,2,1,4              1,2,3,4 .. and etc
    

    然后在TicketNumber 上放置一个索引,那么简单的WHERE TicketNumber = @normalizedTicketNumber 将是一个非常快的索引。

    我实际上认为这是一个可以接受规范化的设计,TicketNumber(连同一个抽奖号码)形成一个密钥。因此,我的论点是:

    1. TicketNumber 是一个不透明的值,它唯一地标识一张票(每个抽奖)。无需了解数据库模型内部的“细节”。 (在某些情况下可能需要,但这里没有。)

    2. DisplayTicketNumber 是用户输入的产物;然而多个 DisplayTicketNumber 可以代表同一个 TicketNumber。虽然这确实表示可能的“重复”,但重要的是要意识到这是一个友好显示值,它代表一个列表(其中包含更多信息比选择的)数字。

      1. 在这种情况下,我会使用触发器使DisplayTicketNumber(和TicketNumber)不可变,以便在创建后不会在此处引入任何数据库不一致。

      2. 如果可以计算 FK,则可以强制执行 DisplayTicketNumber 和 TicketNumber 之间的约束,而无需不变性。

    (我省略了各种细节,例如为不同的莱佛士设置不同的 TicketNumbers 等。我还为 FK 显示了 TicketId,但我也暗示 RaffleId,TicketNumber 是可接受的 [非代理] 键。)

    此外,Ticket 表可以被删除:因为很少有彩票号码集将被共享,所以如果没有额外的关联票信息,那么删除它可能是一个可以接受的 非规范化。这样做的一个好处是TicketNumber 可以移动到Purchase 表中,然后变成一个计算列(它仍然被索引),它标准化了Ticket 值。

    而且,如果 MySQL 允许在 FK 中使用计算列,然后使用关系 PK(Ticket.TicketNumber) -> FK(Purchase.TicketNumber),其中计算 Purchase.TicketNumber可以用于在不消除 Ticket 表的情况下增加模型完整性。 (但是我不使用 MySQL,所以我不能说这是否可行。)

    编码愉快。

    【讨论】:

      猜你喜欢
      • 2012-04-16
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      • 2014-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-07
      相关资源
      最近更新 更多