代理VS自然键:在性能差异的确切数字?(surrogate vs natural key: hard

2019-07-31 10:01发布

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

SO帖子1

SO 2后

我看来,这似乎是大多数(这是一个微弱多数)线,是你应该使用代理键,除非自然键完全是显而易见的,保证不会发生改变。 那么你应该在自然键强制唯一性。 这意味着代理键,几乎所有的时间。

这两种方法,从一个公司表的例子:

1:代理键:表具有ID字段,它是PK(和身份)。 公司名称必须是由国家唯一的,所以有唯一性约束在那里。

2:自然键:表使用公司名称和国家的PK - 同时满足的PK和独特性。

比方说,该公司的PK在其他10桌使用。 我的假设,没有数字来支持它,就是代理键的方法是要快得多在这里。

我已经看到了自然键唯一有说服力的论据是一个多对多的表,它使用两个外键的自然键。 我认为,在这种情况下,这是有道理的。 但是,你可以进入麻烦,如果你需要重构; 这是出于这个职位,我想的范围之内。

有没有人看到,一组使用代理键 同一组采用自然键的表的表比较了性能差异的文章? 环顾SO和谷歌没有取得任何有价值的,只是很多theorycrafting的。


重要更新 :我已经开始建立了一套回答这个问题, 测试表 。 它看起来像这样:

  • PartNatural - 使用独特的零件号为PK部分表
  • PartSurrogate - 使用的ID(INT,同一性)作为PK和对部分号码的唯一索引部分表
  • 植物 - ID(INT,同一性)作为PK
  • 工程师 - ID(INT,同一性)作为PK

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

Answer 1:

同时使用! 自然键防止数据库损坏(不一致可能是一个更好的词)。 当“右”自然键,(消除重复行),将严重,因为长度或参与列数的执行,对性能的目的,代理键可以添加,以及用作其他表,而不是外键自然键......但是自然键仍应以防止数据损坏和enforece数据库一致性备用键或唯一索引...

大部分hoohah(在这个问题上的“辩论”)的,可能是由于什么是一个错误的假设-你必须使用主键在其他表的连接键和外键。 这是假的。 你可以使用任何的对象而在其他表的外键。 它可以是主键,一个备用键,或任何唯一索引或唯一约束。 至于连接,你可以在所有使用任何一个连接条件,它甚至没有成为一个关键,或IDEX,甚至是独一无二的! (不过,如果它不是唯一的,你会在笛卡尔乘积得到多个行会创建)。



Answer 2:

自然键从代理键不同的价值,不会打字。

任何类型的可用于代理键,像VARCHAR为系统生成的slug或别的东西。

然而,最常用的类型代理键是INTEGERRAW(16)或任何类型的RDBMS不使用GUID的)

替代整数和自然数比较(如SSN )恰恰是同一时间。

比较VARCHAR奇妆取整理进去,他们通常比整数更长的时间,这使得它们效率较低。

比较一组两个的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行。

aintadoublebintbdouble包含完全相同的数据,不同之处在于aint具有一个整数作为PRIMARY KEY ,而adouble具有一对两个相同的整数。

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

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



文章来源: surrogate vs natural key: hard numbers on performance differences?