标签: surrogate-key

当我可以使用其他人作为关键字段时,为什么要创建 ID 列?

可能的重复:
为什么使用 int 作为查找表的主键?

到目前为止,我习惯于为每个表创建一个 ID 列,它的实用性使我不必考虑有关主键理论的决策。

我大学的教授建议全班从一个或多个字段制作主键,这些字段构成关于每一列的一个唯一信息。是的,我想养成使用自然键而不是代理键的习惯。维基百科上列出了代理键的优缺点,我严格推荐这篇文章

我见过人们对所有内容都使用整数 ID 字段,但没有人评判这种方法,因为

  • 它“看起来”高效
  • 使用了一个数字字段,它看起来更酷,因为它在内存中每行的大小

我开始认为额外的 ID 字段只是创建冗余数据而没有实际好处。那么当我可以使用其他列作为关键字段时,为什么还要创建 ID 列呢?

  • 如果您的 ID 字段是 32 位,则它已经相当于 4 个 ASCII 字符。
  • 如果您的 Id 字段是64 位整数,则它是8 个字符的字符串,因此它实际上并没有节省那么多内存(这里暗示的是用于比较的内存。额外的 id 列已经添加到使用的内存中(HDD 和 RAM) ) )
  • 额外的 ID 字段会使您的索引成本加倍,因为您还将索引一个可以用作主键的唯一字段。
  • 如果您需要可以用作关键字段的数据,则进行额外的联接,例如,如果您在一篇博客文章中存储了唯一的用户 ID,以显示作者姓名,则进行联接查询,如果您的密钥字段是作者的名字,你不需要加入,因为你将相关数据存储在博客帖子表中。具有有意义数据的外键字段减少了子查询或连接的需要

在此处输入图片说明

  • 创建一个额外的 id 字段“添加”到内存负载,它不是唯一字符串字段的替换,您不是用整数替换 char-varchar 字段,而是添加一个额外的列并创建额外的数据流。所以任何数据存储的比较都应该在“string”和“int+string”之间进行。添加整数 id 字段不节省空间。

另一方面

  • 分配从用户输入中获取价值的主键数据可能会出现问题,因为人们可能会输入错误的社会安全号码,并且由于独特的政策,想要注册的实际人员将无法注册。这可以通过在原始号码上添加一个或多个额外数字来规避。

额外资源:

  1. 自然vc代理键的比较

我从阅读文章中得出的结论是,我应该尽可能使用自然键,而不是每次都跳过考虑自然键并使用代理键,好像这是一个标准。

mysql sql-server primary-key uniqueidentifier surrogate-key

54
推荐指数
4
解决办法
4万
查看次数

每个表都应该有一个单字段代理/人工主键吗?

我了解代理/人工密钥的一个好处 - 它们不会改变,而且非常方便。无论它们是单场还是多场,都是如此——只要它们是“人造的”。

但是,有时将自动递增的整数字段作为每个表的主键似乎是一个策略问题。拥有这样一个单字段键是否总是最好的主意,为什么(或为什么不)?

需要明确的是,这个问题不是关于人工 vs 自然的——而是关于是否所有人工键都应该是单字段的

database-design primary-key surrogate-key

36
推荐指数
3
解决办法
5875
查看次数

与代理整数键相比,自然键在 SQL Server 中提供的性能更高还是更低?

我是代理键的粉丝。我的发现存在确认偏倚的风险。

我在这里和http://stackoverflow.com 上看到的许多问题都使用自然键而不是基于IDENTITY()值的代理键。

我的计算机系统背景告诉我,对整数执行任何比较运算都比比较字符串快。

这个评论让我怀疑我的信念,所以我想我会创建一个系统来研究我的论点,即整数比字符串更快,用作 SQL Server 中的键。

由于小数据集可能几乎没有可辨别的差异,我立即想到了一个两表设置,其中主表有 1,000,000 行,而辅助表在主表中的每一行有 10 行,总共有 10,000,000 行。次要表。我的测试的前提是创建两组这样的表,一组使用自然键,一组使用整数键,并在简单的查询上运行计时测试,例如:

SELECT *
FROM Table1
    INNER JOIN Table2 ON Table1.Key = Table2.Key;
Run Code Online (Sandbox Code Playgroud)

以下是我作为测试台创建的代码:

USE Master;
IF (SELECT COUNT(database_id) FROM sys.databases d WHERE d.name = 'NaturalKeyTest') = 1
BEGIN
    ALTER DATABASE NaturalKeyTest SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    DROP DATABASE NaturalKeyTest;
END
GO
CREATE DATABASE NaturalKeyTest 
    ON (NAME = 'NaturalKeyTest', FILENAME = 
        'C:\SQLServer\Data\NaturalKeyTest.mdf', SIZE=8GB, FILEGROWTH=1GB) 
    LOG ON (NAME='NaturalKeyTestLog', FILENAME = 
        'C:\SQLServer\Logs\NaturalKeyTest.mdf', SIZE=256MB, FILEGROWTH=128MB); …
Run Code Online (Sandbox Code Playgroud)

performance sql-server sql-server-2012 surrogate-key natural-key performance-testing

28
推荐指数
3
解决办法
4879
查看次数

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

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

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

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

foreign-key database-design surrogate-key natural-key

15
推荐指数
2
解决办法
5012
查看次数

代理键违反什么范式?

我有以下问题:

“代理键违反了什么标准形式?”

我的想法是第三范式,但我不太确定这只是我所做的假设。有人可以向我解释一下吗?

normalization surrogate-key relational-theory

8
推荐指数
4
解决办法
4407
查看次数

代理键与自然键

我有一个叫做设备的表。将存储在此表中的大多数设备都可以通过其序列号和部件号进行唯一标识。但是有些设备类型没有分配给它们的序列号和部件号。相反,它们可以由另一个字段(内部 ID)唯一标识。

我应该为此表创建代理键,还是应该创建复合主键(序列号、零件号、内部 ID)并在未提供序列号和零件号列时插入默认值?现在没有部件号和序列号的设备类型将在未来版本中分配给它们编号(可能是 5 年后)。在这种情况下,我应该创建代理键还是复合键?或者使用三个唯一属性,我应该在程序中创建一个哈希并将其用作表的代理键吗?

database-design best-practices surrogate-key natural-key

5
推荐指数
1
解决办法
1054
查看次数

我应该将文档版本字段设置为主键的一部分吗

我应该将文档版本设置为主键吗我正在开发一个文档管理系统,并且我有这两个表代表整个表的一部分。

在此处输入图片说明

在 DocumentVersion 表上,我将主键设置为 (version + documentID) 。如果这是一种推荐的方法,其中 documentID 的类型为 int 而版本的类型为 decimal(5,2) ,那么任何人都可以提出建议吗?或者如果我创建一个新字段并将其设置为 DocumentVersion 表中的主键会更好?谢谢

sql-server-2008-r2 surrogate-key table

4
推荐指数
1
解决办法
408
查看次数

如何利用自然键和代理键实现“两全其美”?DBMS 可以做得更好吗?

我正在设计我的第一个数据库,我发现自己对为分类变量的每个实例存储整数或字符串之间的选择感到沮丧。

我的理解是,如果我有一个包含城市的表,我想将其作为国家/地区表的子级,那么最有效的方法是将国家/地区表的 PK 作为城市表中的 FK。然而,为了便于使用和调试,最好始终将字符串名称与国家/地区 PK 相关联。我考虑过的每个解决方案要么不推荐,要么看起来过于复杂。

我想了解这些方法的优点(或了解新方法),并了解是否必须如此,或者数据库是否只是因为传统而如此。

可能的方法:

  1. 使用字符串作为国家/地区的 PK。然后我将在任何子表中为其提供一个人类可读的 FK。显然,性能不如使用整数,但我怀疑这可能是获得我想要的便利的最不糟糕的方法。

  2. 使用应用程序逻辑创建一个视图,将每个国家/地区的字符串名称连接到 states 表。

  • 我不喜欢这个,因为如果应用程序逻辑中断,表格的可读性就会降低。另外,我预计大型连接操作的性能损失会比字符串 PK/FK 更严重。
  1. 创建一个单独的表以将数字 ID 与相应的字符串 ID 连接起来。我不确定是否有一个表编码每种类型的关系会更好,或者一个大表有一个大的 ID 池来覆盖所有整数键字符串值关系。然后,我可以使用应用程序逻辑查找适当的字符串,并在用户给出字符串名称时将适当的 PK 填充到子表中。
  • 我觉得这也可能是相当资源密集型的,因为每次向子级添加新行时都必须进行查找。这也意味着我仍然需要创建我想要的视图。
  1. 使用enum数据类型。出于本能,这将是我的首选方法,因为它似乎是自然键和合成键之间的理想平衡:使用整数 ID 并为 ID 提供字符串标签,以便字符串本身不需要重复。
  • 不幸的是,我的研究发现不建议这样做。原因之一是类别不能轻易删除。我不确定这对我来说是否是一个破坏性的因素,但我也想知道为什么 DBMS 是这样设计的。难道分类变量的常用程度不足以为它们添加便利功能吗?

foreign-key primary-key surrogate-key enum natural-key

2
推荐指数
1
解决办法
892
查看次数

使用代理键的缺点是什么?

我正在使用 MS SQL Server,但在一般数据库设计中,我想知道当数据库中的每一行都有其自动生成的代理键值时会出现什么问题。

我知道一些优点,比如主键不需要标识没有NULL的唯一列,不需要管理复合主键,范式更容易管理,唯一性有保证。

我想知道,是否有任何关于性能或索引结构等的充分理由应该使我们使用真实世界的事实键而不是代理键?

谢谢。

database-design primary-key surrogate-key candidate-key

0
推荐指数
1
解决办法
1244
查看次数