有一个健康的辩论,那里之间的代理和自然键:

此后1

此后2

我的意见,这似乎是符合大多数(它是一个苗条的大部分),是的,你应该使用代理键除非一个自然的关键是完全显而易见的,并保证不改变。那么你应该强制执行的独特性在于自然的关键。这意味着替代键的几乎所有的时间。

例两种做法,开始与一家公司表:

1:代理关键:表格有一个ID领域,这是PK(和身份)。公司名字都需要独特的状态,因此,有一个独特的约束。

2:自然的关键:表使用的公司名称和状态如PK--满足这两个PK和独特性。

让我们说,该公司PK是用在其他10个表格。我的假设,没有数字备份的是,替代关键的方法将会更快在这里。

只有令人信服的论点我已经看到对自然关键的是对于许多许多的表使用的两个外键作为一个自然的关键。我认为在这种情况下,它才有意义。但你可以得到的麻烦,如果您需要重构;这是出的范围这一职位,我认为。

有人看到一篇文章,比较 性能差异 在一套表格,使用 代理键 同样的一套表格的使用 自然键?看就这么和谷歌还没有取得任何有价值的,只是一个很大的theorycrafting.


重要的更新:我已经开始建筑一个 设定的测试表 这回答这个问题。它看起来像这样:

  • PartNatural件表使用的 独特的部分号码作为一PK
  • PartSurrogate件表 使用一个ID(int、身份)作为PK 有一个独特的索引部分号码
  • 植物-ID(int、身份)作为PK
  • 工程师-ID(int、身份)作为PK

每一个部分是加入工厂以及每个实例的一部分,在工厂是加入一个工程师。如果任何人有一个问题,这个试验台,现在是时候。

有帮助吗?

解决方案

使用两个!自然键的防止腐败数据库(不一致可能是一个更好的词)。在"正确的"自然键,(消除重复行)将执行严重,因为长度,或列数参与,对于性的目的,代理键,可以加入,以及被用作外键的其他表中,而不是自然钥匙...但自然的关键应该保持作为备用钥匙或唯一的索引,以防止数据的腐败和enforece数据库的一致性...

许多hoohah(在"辩论"上,这一问题),可能是由于什么是一种错误的假设-你有用 主钥匙 对于加入和外键在其它表格。这是错误的。你可以使用任何 关键 作为目标的外国钥匙在其它表格。它可以主要关键,一个备用的钥匙,或者任何独特的索引或独特的约束。和作为联接,可以使用任何东西所有的加入条件,它甚至没有是一个关键的,或者一个国际定单册,或者甚至是独一无二的!!(但如果它是不是独一无二的,你会得到多个行在笛卡尔的产品创建).

其他提示

自然键不同代理键在价值,而不是类型。

任何类型可用于替代关键的,就像 VARCHAR 该系统生成的 slug 或别的东西。

然而,大多数使用的类型用于替代键是 INTEGERRAW(16) (或任何类型的你 RDBMS 不会使用 GUID's),

比较替代整数和天然整数(喜欢 SSN)需要完全相同的时间。

比较 VARCHARs使需要的排序规则的考虑和它们一般长于整数,即使他们不太有效。

比较集中的两个 INTEGER 也可能效率低于比较一个单一的 INTEGER.

在数据类型小这种差异可能是 百分比的百分比 所需要的时间取页,横行的索引,acquite数据库锁等。

和这里的数字(在 MySQL):

CREATE TABLE aint (id INT NOT NULL PRIMARY KEY, value VARCHAR(100));
CREATE TABLE adouble (id1 INT NOT NULL, id2 INT NOT NULL, value VARCHAR(100), PRIMARY KEY (id1, id2));
CREATE TABLE bint (id INT NOT NULL PRIMARY KEY, aid INT NOT NULL);
CREATE TABLE bdouble (id INT NOT NULL PRIMARY KEY, aid1 INT NOT NULL, aid2 INT NOT NULL);

INSERT
INTO    aint
SELECT  id, RPAD('', FLOOR(RAND(20090804) * 100), '*')
FROM    t_source;

INSERT
INTO    bint
SELECT  id, id
FROM    aint;

INSERT
INTO    adouble
SELECT  id, id, value
FROM    aint;

INSERT
INTO    bdouble
SELECT  id, id, id
FROM    aint;

SELECT  SUM(LENGTH(value))
FROM    bint b
JOIN    aint a
ON      a.id = b.aid;

SELECT  SUM(LENGTH(value))
FROM    bdouble b
JOIN    adouble a
ON      (a.id1, a.id2) = (b.aid1, b.aid2);

t_source 只是一个虚拟的表 1,000,000 排。

aintadouble, bintbdouble 包含的数据相同,只是 aint 有一个整数作为一个 PRIMARY KEY, 同时 adouble 有一对两个相同的整数。

我的机器上,这两个运行查询14.5秒钟,+/-0.1秒

性能差,如果有的话,是内的波动范围。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top