【问题标题】:Advantage / disadvantage of using foreign keys on every child table to all parents/grand parents, etc?在每个子表上对所有父母/祖父母等使用外键的优点/缺点?
【发布时间】:2010-12-10 20:51:03
【问题描述】:

如果有的话,将所有子表作为外键链接到层次结构中它们之上的所有表有什么害处?我有一个包含 6 个查找表的位置组件:

  • 各大洲
  • 国家/地区
  • 地区
  • 城市
  • 社区
  • 位置类型

显然每个级别的位置都是上述位置的子级,因此它将外键到父级,但是如果我将它们全部外键在一起有什么害处,那就是我的城市表有:

城市表

  • continent_id(转至大陆)
  • country_id(转至国家/地区)
  • region_id (fk to region)

vs 只有'region_id-fk to region'?

我看到的好处是,如果我必须在一个大陆上查找城市,我可以直接从一个城市到另一个大陆,而无需跳转到区域然后国家然后大陆,但是我当然不确定缺点,或者如果这影响性能还是其他什么?

这是一组表。我有很多这样的表,所以我试图理解这个概念,这样我就可以用它来设计其他表,也可以在我的其他组件上设计,这些表远远超过 6 个查找表。

【问题讨论】:

    标签: database database-design


    【解决方案1】:

    危害在于denormalization(又名重复)数据。

    如果您已经有 FK 链接,在层次结构的最后一个表中重复它们意味着您正在重复数据,如果您需要更改它,您将不会在多个位置拥有它。

    此外,在您的多 FK 方案中,除非您添加更多检查约束,否则您最终可能会在 city 表中得到不一致的数据(其中国家和大陆不匹配)。

    【讨论】:

    • 但是这里有什么比什么更重要?进行 2-3-4 连接以到达父表更好还是通过 fks 对其进行非规范化以便每个人之间存在直接关系?我假设由于所有表都通过 FK 相关,因此没有重复,因为它们都相关。所以我不能在一张桌子上输入“New York”,在下一张桌子上输入“new yk”。所以将存在相同的数据 - 是的,但它在所有表格中总是准确的。这是一个社交网络,所以性能很重要,因此我不确定。
    • @mikey - 使用您的多 FK 方案,您可以在美国和非洲拥有一个城市,除非您添加更多检查约束。
    • 例如:从芝加哥到伊利诺伊州到美国到北美。是的,如果我在国家/地区的城市表中输入错误的 fK id,它可能会去:芝加哥到伊利诺伊州到非洲到北美。但我认为这是会出错的地方,因为区域表中有芝加哥到伊利诺伊州和伊利诺伊州到美国的 FK,所以它不会检查“伊利诺伊州到非洲”在区域表中是否无效,从而防止出现城市表中芝加哥与非洲之间的联系?
    • @mikey - 它不会检查整个层次结构的 FK。如果您为国家表定义一个 FK,它将确保一个有效的国家/地区和另一个到大洲表,它将简单地确保它是一个 有效 大陆。它不会确保各个国家/地区的 FK 与您的表格中的相同。
    • 嗯,如果有强制mysql检查整个层次结构或部分层次结构的FK有效性的方法是什么?必须有一些声明或解决方法,因为我怀疑像军事数据库这样的大型系统是否会在 3NF 中定义所有内容,这会创建大量表。
    【解决方案2】:

    @mikey - 抱歉,我认为我没有资格评论其他答案 - 无论如何:

    对于非规范化的单表方法,五(六?)列上的复合主键是否足够?

    在单表非规范化或多表规范化方法之间做出决定时的另一个考虑因素是,您为更高级别的实体存储了哪些附加属性?例如,您只是存储城市名称,还是还想要纬度/经度对、电话拨号代码等?您想要存储的属性越多,在非规范化模型中就会出现越多的重复(以及相关的数据管理问题)。

    【讨论】:

      【解决方案3】:

      我通常不会以这种方式执行传递外键。一般来说,这会导致很多额外的头痛和许多额外的问题机会。保持简单。我不认为这本身就是一个非规范化问题。这只是保持事情可控的问题。考虑以下几点:

      CREATE TABLE employee (
          control code text primary key,
          date_of_birth date not null,
          ..,..
          id serial not null unique
      );
      
      CREATE TABLE wage_salary ( -- owners have drawings, not salaries, so this avoids nulls
          employee_id int not null references employee(id),
          wage_amt numeric not null,
          per_interval interval not null,
          primary key (employee_id)
      );
      
      CREATE TABLE reported_wages ( -- for tax purposes
          employee_id int not null references wage_salary,
          year int not null,
          reported_wages numeric not null,
          PRIMARY KEY (employee_id, year),
          FOREIGN KEY (employee_id) REFERENCES employee(id) -- unnecessary and troublesome
      );
      

      在许多情况下,多余的冗余外键会咬你。由于它是传递性强制执行的,因此将其关闭。

      【讨论】:

        猜你喜欢
        • 2020-07-25
        • 1970-01-01
        • 2015-08-10
        • 1970-01-01
        • 2011-01-12
        • 2015-08-30
        • 1970-01-01
        • 2016-08-18
        • 2017-04-17
        相关资源
        最近更新 更多