AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 39058
Accepted
Chris J
Chris J
Asked: 2013-04-03 04:17:56 +0800 CST2013-04-03 04:17:56 +0800 CST 2013-04-03 04:17:56 +0800 CST

外键 - 使用代理或自然键链接?

  • 772

对于表之间的外键是否应该链接到自然键或代理键,是否有最佳实践?我真正找到的唯一讨论(除非缺少我的 google-fu)是Jack Douglas 在这个问题中的回答,他的推理对我来说似乎是合理的。我知道除了规则更改之外的讨论,但这将是在任何情况下都需要考虑的事情。

问的主要原因是我有一个遗留应用程序,它使用带有自然键的 FK,但是开发人员强烈推动转向 OR/M(在我们的例子中是 NHibernate),并且一个 fork 已经产生了一些重大更改,因此我希望使用自然键将它们推回正轨,或者移动旧版应用程序以使用 FK 的代理键。我的直觉说要恢复原来的 FK,但老实说,我不确定这是否真的是正确的道路。

我们的大多数表已经定义了代理键和自然键(尽管唯一约束和 PK),因此在这种情况下,必须添加额外的列对我们来说不是问题。我们使用的是 SQL Server 2008,但我希望这对于任何数据库来说都足够通用。

database-design foreign-key
  • 3 3 个回答
  • 5413 Views

3 个回答

  • Voted
  1. Best Answer
    Mike Sherrill 'Cat Recall'
    2013-04-03T06:09:01+08:002013-04-03T06:09:01+08:00

    SQL 和关系模型都不会受到引用自然键的外键的干扰。事实上,引用自然键通常会显着提高性能。您会惊讶地发现您需要的信息完全包含在自然密钥中的频率。引用该键会将连接换成更宽的表(从而减少您可以在一页中存储的行数)。

    根据定义,您需要的信息始终完全包含在每个“查找”表的自然键中。(术语查找表是非正式的。在关系模型中,所有表都只是表。美国邮政编码表的行可能如下所示:{AK, Alaska}, {AL, Alabama}, {AZ, Arizona}等。大多数人会称之为查找表。)

    在大型系统上,找到具有多个候选键的表并不罕见。服务于企业的一部分的表引用一个候选键,而服务于企业的另一部分的表引用不同的候选键也很常见。这是关系模型的优势之一,也是 SQL 很好支持的关系模型的一部分。

    当您在也有代理键的表中引用自然键时,您会遇到两个问题。

    首先,你会让人们大吃一惊。虽然我通常强烈游说最小意外原则,但这是我不介意让人们感到惊讶的一种情况。当问题是开发人员对外键的逻辑使用感到惊讶时,解决方案是教育,而不是重新设计。

    其次,ORM 通常不是围绕关系模型设计的,它们有时会包含不反映最佳实践的假设。(事实上​​,它们的设计似乎常常没有来自数据库专业人员的输入。)要求在每个表中都有一个 ID 号是这些假设之一。另一种假设是 ORM 应用程序“拥有”数据库。(因此可以自由地创建、删除和重命名表和列。)

    在 30 年的时间里,我曾在一个数据库系统上工作,该系统为数百个应用程序提供数据,这些应用程序至少用两打语言编写。该数据库属于企业,而不是 ORM。

    引入重大更改的分叉应该是一个展示停止器。

    在我曾经工作过的公司,我使用自然键和代理键测量了性能。有一个临界点,代理键开始优于自然键。(假设没有额外的努力来保持自然键的高性能,比如分区、部分索引、基于函数的索引、额外的表空间、使用固态磁盘等。)根据我对那家公司的估计,他们将在大约 2045。与此同时,它们使用自然键获得了更好的性能。

    其他相关答案:In Database Schema Confusing

    • 16
  2. HLGEM
    2013-04-03T09:49:30+08:002013-04-03T09:49:30+08:00

    我支持代理键的主要原因是自然键经常会发生变化,这意味着必须更新所有相关的表,这会给服务器带来很大的负担。

    在 30 年里,我一直在使用各种数据库来处理许多主题,真正的自然键通常相当罕见。事物被认为是唯一的(SSN)不是,在特定时间唯一的事物以后可能会变得不唯一,并且电子邮件地址和电话号码等某些事物可能是唯一的,但它们可以在以后重新用于不同的人日期。当然,有些东西根本没有像人名和公司名这样的良好唯一标识符。

    至于通过使用自然键来避免连接。是的,这可以加快不需要连接的 select 语句,但它会导致您仍然需要连接的地方变慢,因为 int 连接通常更快。它还可能会减慢插入和删除速度,并在密钥更改时导致更新性能问题。复杂的查询(反正更慢)会更慢。所以简单的查询速度更快,但报告和复杂的查询以及针对数据库的许多操作可能会更慢。这是一种平衡行为,根据查询数据库的方式,可能会以一种或另一种方式倾斜。

    所以没有一刀切的答案。这取决于您的数据库以及查询方式以及其中存储的信息类型。您可能需要进行一些测试以找出最适合您自己的环境的方法。

    • 5
  3. philn5d
    2014-08-16T05:01:47+08:002014-08-16T05:01:47+08:00

    如果您不知道答案,请选择代理人。这就是为什么 - 如果对业务规则做出假设,并且这些假设是错误的或规则发生变化,那么您的数据就是垃圾。这是一个例子:

    人物、角色、人物角色

    当前的业务规则规定一个人只有一个角色。您制作了一个将 Person 和 Role 链接起来的表,其中 PersonRole (PersonName, PersonBirthDate, PersonMotherMaidenName, ..., RoleCode)

    现在,当谈到 Natural Keys 时,您是真正的纯粹主义者!但说真的,如果组织决定一个人现在可以担任多个角色怎么办?支持业务需求变化的下游效应是什么?

    • -4

相关问题

  • 过滤索引是否有助于改进基于输入时间的查询,还是应该避免这种情况?

  • MySQL VARCHAR 和 TEXT 数据类型有什么区别?

  • 存储计算值或根据要求重新计算它们更好吗?[复制]

  • 存储与计算聚合值

  • 在数据仓库中实现多对多关系有哪些方法?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    授予用户对所有表的访问权限

    • 5 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve