在关系数据库中存储和引用不可变的有序列表

时间:2014-11-10 17:23:11

标签: mysql sql sql-server database relational-database

背景:我有一个包含父母孩子名字的数据库(这是对实际数据的简化,但类比很接近足够)。

任务:数据库必须为每个存储儿童姓名有序列表

假设:

  1. 数据库将包含数百万个父母,可能还有更多。
  2. 父母通常不超过4或5个孩子,但也必须支持罕见(甚至极端)的病例。
  3. 儿童的名字(以及订购)往往会重复很多。所以父母应该引用一些children_names_list_id而不是保留实际名称的副本。
  4. 儿童的姓名以及他们对特定父母的排序是不可变的。
  5. 新父母的插入将非常频繁。当插入新父项及其子项列表时,如果数据库中已存在这样的名称列表,则新父项应引用现有列表标识符。
  6. 有关名称及其排序的查询应该是可能的(例如 - 在命名一个孩子“Alice”之后找到所有为孩子命名的父母“Bob”,或者找到所有名字的父母一个孩子“爱丽丝”,然后有两个孩子,第三个名为“卡罗尔”等)
  7. 问题:

    1. 存储此类列表的最佳方法是什么?该解决方案应该是健壮的,并支持快速插入父项。
    2. 父母应该如何引用这些列表?
    3. 当前(建议)解决方案:

      我目前的方法是建立一个表格,将子名称映射到整数名称ID (名称很长,整数很短)。 然后在以下元组中存储名称列表:<list_id> <order> <name_id>,因此列表将如下所示:

      <list_id> <order> <name_id>
          1       1       123
          1       2       345
          1       3       678
          2       1       901
          3       1       123
          3       1       901
      

      示例表包含三个列表:[123,345,678],[901],[123,901],可能对应于:[“Alice”,“Bob”,“Carol”],[“Dave”],[“爱丽丝“,”戴夫“] 然后,父表将有一个引用children_list_id列的list_id列。

      除了两个问题外,这个解决方案似乎很强大:

      1. 我不确定插入是否足够快(查看现有列表是否已经存在似乎可能很慢),但其他方法似乎不那么健壮或者(更难)查询。
      2. 名单列表的关键字由list_idorder列组成; parent表必须仅引用应该是外键的list_id,但由于list_id在列表中本身不是一个键,所以另外还有一个列表表,其中{{1}是关键是需要的。这看起来很麻烦。
      3. 替代解决方案:

        列表将在列中存储隐式排序:

        list_id

        在此表中,<list_id> <name_1> <name_2> <name_3> <name_4> ... <name_100> 1 111 222 333 null 2 444 null 3 555 111 null 将成为主键。

        parent表将list_id保留为外键。

        这个解决方案不太健壮(我创建了多少列?10?20?50?),但插入速度更快。由于list_id是关键,因此不需要额外的表。然而,可能的缺点是某些查询变得更加复杂,因为它们必须引用多个列。

        谢谢!

1 个答案:

答案 0 :(得分:1)

list表格过度设计。只需要一个Parents表,一个Names表和一个ParentChildren表。除了一些细节之外,ParentChildren表就像列表一样。它看起来像是:

<ParentId> <Order> <NameId>
    1         1     123
    1         2     345
    1         3     678
    2         1     901
    3         1     123
    3         1     901

我没有看到存储独立列表的特别节省。只需为每位父母存储孩子。