代理与自然/业务密钥的比较[关闭]


178

再来一次,旧的争论仍然浮现...

我们是否最好将业务密钥作为主键,还是宁愿使用在业务密钥字段上具有唯一约束的代理ID(即SQL Server身份)?

请提供示例或证明来支持您的理论。


25
@Joachim Sauer:关于事物是否是主观的争论本身可能是主观的,而这与所讨论事物的客观性或主观性没有任何关系。除非您准备陈述使某件事变得客观的确切客观标准。有一些所谓的“开放概念”,例如留胡子的头发数。可以客观地说,没有下巴头发的人没有胡须,而一英寸长5,000根头发的人却没有胡须,但是在中间的某个地方需要主观判断才能做出客观的决定。
ErikE

@Manrico:您只需要问自己一个问题:如果我不使用代理键,我的主键是否仍然是不变的?如果答案是否定的,那么您应该认真考虑使用代理密钥。另外,如果主键甚至部分是由用户输入组成的,则应考虑使用代理键。为什么?由于存在数据异常的危险。
code4life

@TylerRick但这不是一个很好的问题。它要求一种通常适用于所有情况的解决方案,当显然没有一种情况时,正如问问者充分意识到的“宗教战争”所证明的那样(引用:“在这里,我们再去一次,仍然有旧论点出现。 ..”)。与其想知道世界是否已经改变,最后没有提出一个始终必须选择一方的令人信服的理由,不如对每种具体情况一遍又一遍地问这个问题,并在不确定时张贴到SO上。 。这只会引起教条主义。
MarioDS '16

Answers:


100

都。吃蛋糕吃吧。

请记住,主键没有什么特别之处,只是它被标记为这样。它不过是一个NOT NULL UNIQUE约束,一个表可以有多个。

如果使用代理密钥,您仍需要一个业务密钥来确保根据业务规则的唯一性。


7
如果您有多个“候选”键(字段或非空唯一的相同大小的字段集合),则可能违反了Boyce-Codd正常形式。BCNF超出了3NF,因此没有多少人担心它。但是,在某些情况下,使用BCNF非常有帮助。
艾伦(Alan)

2
同意 真正的问题应该是:我应该在表中添加唯一的代理键吗?另一个完全不同的问题是逻辑主键使用什么。它们本质上都是非空唯一索引约束。
dkretz

1
“每个问题都可以通过间接的另一个层次来解决” ...代理密钥就在于:另一个间接的层次
Steve Schnepp

5
我感到奇怪的是,许多评论似乎断言没有代理密钥就无法建立关系。在许多情况下,代理密钥是多余的。为什么添加没有价值却增加技术债务的东西(在某些情况下,会导致原本独特的结果突然变得不唯一)。
Deyon Samuel Washington

2
它不仅仅是NOT NULL UNIQUE约束。主键用作聚集索引,可确定数据的物理顺序。通常,Integer易于平衡,因为它会按顺序递增,并且您的数据将附加到磁盘上的EOF。如果您使用较少的顺序数据(例如文本或GUID(UUID)),则会有更多的磁盘IO和平衡索引的工作,我认为这是一个很大的不同
Jin

126

使用代理键的几个原因:

  1. 稳定性:由于业务或自然需求而更改密钥将对相关表产生负面影响。代理键很少(如果有的话)需要更改,因为与值无关。

  2. 约定:使您可以使用标准化的“主键”列命名约定,而不必考虑如何将具有各种名称的表联接到其PK。

  3. 速度:取决于PK值和类型,整数的替代键可能更小,索引和搜索更快。


2
现在,在阅读了很多有关代理键和自然键的信息之后,我认为使用代理键会更好。但是,在我的数据库上,自然键(NVARCHAR(20))必须是唯一的。我不明白如果我需要检查该列上的每个数据以不对每个插入重复任何值(使用NOT NULL UNIQUE约束),那么如何提高速度。
VansFannel '16

据我所知,@ VansFannel为确保唯一性而创建的索引将在您插入/更新值时检查重复性。
Ziyaddin Sadigov

72

似乎还没有人说过任何支持非代理(我犹豫要说“自然”)键的内容。所以这里...

代理键的一个缺点是它们无意义(某些人认为是优点,但是...)。有时这迫使您将比实际需要更多的表联接到查询中。相比:

select sum(t.hours)
from timesheets t
where t.dept_code = 'HR'
and t.status = 'VALID'
and t.project_code = 'MYPROJECT'
and t.task = 'BUILD';

反对:

select sum(t.hours)
from timesheets t
     join departents d on d.dept_id = t.dept_id
     join timesheet_statuses s on s.status_id = t.status_id
     join projects p on p.project_id = t.project_id
     join tasks k on k.task_id = t.task_id
where d.dept_code = 'HR'
and s.status = 'VALID'
and p.project_code = 'MYPROJECT'
and k.task_code = 'BUILD';

除非有人认真地认为以下是一个好主意?

select sum(t.hours)
from timesheets t
where t.dept_id = 34394
and t.status_id = 89    
and t.project_id = 1253
and t.task_id = 77;

“但是”有人会说,“当MYPROJECT或VALID或HR的代码更改时会发生什么?” 我对此的回答是:“为什么需要更改它?” 从某种意义上讲,这些不是“自然”键,某些外部主体将立法规定从此以后将“ VALID”重新编码为“ GOOD”。实际上只有一小部分“自然”密钥属于此类-SSN和Zip代码是常见示例。我肯定会对诸如Person,Address之类的表使用无意义的数字键,但不会对所有内容使用,这出于大多数人在某些情况下似乎都提倡的原因。

另请参阅:我对另一个问题的回答


14
-1自然键作为主键的问题是,对于每个子表,您都必须添加由多个字段(而不是代理键的一个字段)组成的父键。键。因此,请想象以下情况,其中从TABLEA开始的关系是1-0 .. *:TABLEA PK:ID_A TABLEB PK:ID_A ID_B TABLEC PK:ID_A ID_B ID_C TABLED PK:ID_A ID_B ID_C ID_D。看到问题了吗?父键在子表中传播。如果TABLEA的主键更改,会发生什么?现在,您也必须重构所有子表PK。
阿尔弗雷多·奥索里奥

9
@Alfredo:是的,当然需要权衡。但是,在我20多年的经验中,我很少看到表格PK更改的定义。如果它定期发生,我也可能会避免使用自然键。实际上,在极少数情况下会发生这种情况,我准备承受扩展影响的打击。
托尼·安德鲁斯

10
我不同意。通常,某些外部机构(客户)立法要求对自然键进行编辑,并因此在整个系统中进行传播。我看到这经常发生。您可以确保不再需要更改密钥的唯一方法是定义为无意义的密钥。此外,现代数据库非常高效地处理内部联接,因此使用代理替代所带来的潜在的大空间收益通常胜于不必执行那么多内部联接的优势。
TTT 2012年

8
@TTT:那设计一开始就很薄弱。同样,这是男人与男孩分开的地方:正确选择何时使用自然键以及何时使用替代键。您决定按表而不是一般教条。
DanMan

7
我也有20多年的经验,我赞成你的看法。我曾经用代理密钥创建了一个oracle数据仓库,数据维护就像地狱一样。您根本无法直接访问您的数据。您总是需要为所有内容编写查询,这使得代理键简直难以处理。
SQL警察

31

代理密钥永远不会有更改的理由。我不能对自然键说同样的话。姓氏,电子邮件,ISBN编号-它们都可以改变一天。


30

代理键(通常是整数)具有使您的表关系更快,在存储和更新速度上更经济的附加值(更好的是,与业务键字段相比,使用代理键时不需要更新外键,确实会不时发生变化)。

表的主键应用于唯一地标识行,主要用于连接目的。考虑一个人表:名称可以更改,并且不能保证唯一。

Think公司:您是与Merkia中其他公司开展业务的快乐Merkin公司。您非常聪明,没有将公司名称用作主键,因此您可以使用Merkia政府的唯一公司ID(全部由10个字母数字字符组成)。然后Merkia更改了公司ID,因为他们认为这是个好主意。可以,您可以使用数据库引擎的级联更新功能进行更改,而该更改首先不应该涉及您。后来,您的业务扩展了,现在您在Freedonia的一家公司工作。Freedonian公司ID最多16个字符。您需要扩大公司ID主键(以及订单,发货,MoneyTransfers等中的外键字段),并在主键(也包括外键)中添加国家/地区字段。哎哟! 弗里多尼亚的内战,分为三个国家。您的同事的国家/地区名称应更改为新的国家/地区名称;级联更新以进行救援。顺便说一句,您的主键是什么?(国家/地区,公司ID)还是(国家/地区,公司ID)?后者有助于联接,前者避免另一个索引(或者,如果您也希望按国家/地区对订单进行分组,则可能避免多个索引)。

所有这些都不是证明,而是一种指示,用于唯一标识所有用途(包括联接操作)的行的代理键比业务键更可取。


您将以最酷的用户名赢得所有互联网!
伊恩·霍尔德

1
那几乎就是不赞成票的意思:“我不同意这一点。”
jcollum

5
向下箭头的工具提示显示“此答案没有用”,而不是“我不同意”。也许在这个特定的答案中,含义很接近,但是它们通常并不相同。
tzot

1
如果有人认为您的答案是错误的,那么他(她)也将认为它使提问者进入错误的方向(与正确的方向相反),因此将判断您的答案比“无助”还差,在他(她)的脑海里证明自己是反对派。
Erwin Smout,2011年

1
是的,代理密钥是一种疾病。一个泄漏到野外,您将其用作pkey,因此现在您需要自己的代理密钥。然后,您的密钥泄漏到野外(例如通过URL),疾病传播。
塞缪尔·丹尼尔森

26

我一般不喜欢替代键。仅当没有可用的自然键时才应使用它们。考虑一下这是很荒谬的,认为向表中添加无意义的数据可以使事情变得更好。

这是我的原因:

  1. 使用自然键时,表以最常搜索的方式聚集在一起,从而使查询速度更快。

  2. 使用代理键时,必须在逻辑键列上添加唯一索引。您仍然需要防止逻辑重复数据。例如,即使pk是代理ID列,您也不能在组织表中允许两个具有相同名称的组织。

  3. 当使用代理键作为主键时,自然主键是什么就不太清楚了。开发时,您想知道哪些列使表唯一。

  4. 在一对多的关系链中,逻辑钥匙链。因此,例如,组织有许多帐户,而帐户有许多发票。因此,组织的逻辑键是OrgName。帐户的逻辑键是OrgName,AccountID。发票的逻辑键是OrgName,AccountID,InvoiceNumber。

    使用代理键时,仅对直接父级具有外键会缩短键链。例如,“发票”表没有“组织名称”列。它只有一个AccountID列。如果要搜索给定组织的发票,则需要加入组织,帐户和发票表。如果使用逻辑键,则可以直接查询组织表。

  5. 存储查找表的替代键值会使表中填充无意义的整数。要查看数据,必须创建连接到所有查找表的复杂视图。查找表旨在为列保留一组可接受的值。不应通过存储整数代理键来进行编码。规范化规则中没有任何内容建议您存储替代整数而不是值本身。

  6. 我有三本不同的数据库书籍。其中没有一个显示使用代理键。


7
我讨厌代理键,除非有必要。当企业使用受很多错误影响的自然键,并且不愿意容忍受这些错误影响的数据库时,它们是必需的。
Walter Mitty

26
-1:我编写并维护了许多应用程序。与数据最相关的问题是那些使用自然键的问题。
猎鹰

6
您的某些观点假设代理键必须是PK或必须是聚簇列-不正确。您的第1点和第5点忽略了以下事实:整数是4个字节,而自然键几乎总是很多很多。而且,每个非聚集索引必须重复聚集索引中那些自然键的字节,因此自然键数据库中的表和索引每页的行数要少得多,这将导致读取性能大大降低。,这会使查询变慢,而不是变快。
ErikE

3
反对自然键的另一个原因(例如:原子序号,VIN等),业务逻辑可以更改,从而增加了数据类型。例如-之前:跟踪原子的电荷,之后:跟踪原子和化合物的电荷。之前:跟踪机动车辆的负载能力。之后:增加飞机,轮船,自行车和人的承载能力。
forforf 2013年

3
我猜您没有任何表,其中主键甚至部分由以下组成:1)任何可以改变的属性,或2)用户输入的信息(例如,动态生成的查找列表)。如果不能保证密钥的不变性,则必须通过代码或手动“修复”脚本来更新所有这些实体关系。如果您从不需要这样做...我想您的数据库既是替代密钥的,又是...非同寻常的。
code4life

18

我想与您分享我在这场无休止的战争中的经验:关于自然与替代关键难题的D。我认为,这两个代理键(人工自动生成的)和自然键(列(S组成)与域的意思)有优点缺点。因此,根据您的情况,选择一种或另一种方法可能更相关。

似乎很多人将替代密钥作为几乎完美的解决方案,而将自然密钥作为瘟疫,因此,我将集中讨论另一种观点的论点:

代理键的缺点

代理键是:

  1. 性能问题的根源:
    • 它们通常使用自动递增的列来实现,这意味着:
      • 每次您想要获取新的ID时都要往返数据库(我知道可以使用缓存或类似的算法来改善这一点,但这些方法仍然有其自身的缺点)。
      • 如果有一天您需要将数据从一种模式转移到另一种模式(至少在我的公司中经常发生),那么您可能会遇到ID冲突问题。是的,我知道您可以使用UUID,但是这些持续时间需要32个十六进制数字!(如果您关心数据库的大小,则可能是一个问题)。
      • 如果您对所有代理键都使用一个序列,那么-可以肯定-您最终将在数据库中发生争用。
  2. 容易出错。序列具有max_value限制,因此-作为开发人员-您必须注意以下几点:
    • 您必须循环序列(达到最大值后,它会回到1,2,...)。
    • 如果将序列用作数据的排序(随时间变化),则必须处理循环的情况(编号为1的列可能比编号为max-value-1的行新)。
    • 确保您的代码(甚至应该是不应作为内部ID发生的客户端接口)都支持用于存储序列值的32b / 64b整数。
  3. 他们不保证不会重复的数据。您始终可以拥有两行,它们的列值都相同,但生成的值却不同。对我来说这是THE从一个数据库设计点代理键的问题。
  4. Wikipedia中的更多内容...

关于自然键的神话

  1. 复合键的效率比代理键低。没有!这取决于使用的数据库引擎:
  2. 自然键在现实生活中不存在。对不起,但它们确实存在!例如,在航空业中,以下元组对于给定的预定航班(航空公司,出发日期,flightNumber,operationsSuffix)将始终是唯一的。更一般地,当通过给定的标准保证一组业务数据是唯一的时,则该组数据是[良好]自然密钥候选者。
  3. 自然键“污染子表”。对我来说,这不是真正的问题,而是更多的感觉。具有4列,每个2字节的主键可能比单列11个字节的效率更高。此外,这4列可用于直接查询子表(通过在where子句中使用4列),而无需联接到父表。

结论

在需要时使用自然键,在最好使用时使用代理键。

希望这对某人有所帮助!


3
重新安排预定航班的出发日期会怎样?您是否必须跟踪所有相关实体并删除密钥,还是实际上要更新相关实体中的所有密钥?还是在处理一个简单的单数表(甚至可能不是3NF)?
code4life

卓越点@ code4life
forcewill '16

@ code4life:这就是OperationalSuffix插入的地方。为了保持相同的flightNumber,以便避免客户端混淆,我们仅添加一个后缀(例如,“ D”)。
mwnsiri '16

“您始终可以拥有两行,所有行具有相同的列值,但生成的值却不同”,因此只需在您的列上放置唯一或复合唯一约束。
wha7ever

15

始终使用没有商业意义的密钥。这只是个好习惯。

编辑:我试图在线找到它的链接,但我找不到。但是,在“企业架构模式” [Fowler]中,它很好地解释了为什么您不应该使用除了键以外的任何东西,而除了键之外没有其他含义。归结为这样的事实,即它应该只有一份工作和一份工作。


22
Martin Fowler可能有很多事情,但他不是数据库设计的权威。
托尼·安德鲁斯

我认为您应该在得出结论之前提供一些推理。
阿内·埃弗森

4
@ArneEvertsoon原因在那里。归根结底,它应该只有一份工作和一份工作。单一责任。
伊恩·霍尔德

10

如果您打算使用ORM工具来处理/生成数据类,则代理键非常方便。虽然您可以将组合键与某些更高级的映射器(请参阅:休眠)结合使用,但它会增加代码的复杂性。

(当然,数据库纯粹主义者会争辩说,即使代理密钥的概念也是可憎的。)

我喜欢在适当的时候使用uids作为代理键。使用它们的主要好处是您事先知道密钥,例如,您可以创建一个类的实例,该实例的ID已经设置并且保证是唯一的,而使用整数密钥,则需要默认为0或- 1,并在保存/更新时更新为适当的值。

但是,UID在查找和连接速度方面会受到惩罚,因此,UID是否可取取决于所讨论的应用程序。


6

在我看来,使用代理密钥比较好,因为更改的可能性为零。我几乎可以想到的任何可以用作自然键的东西都可能改变(免责声明:并不总是正确的,但通常是这样)。

一个示例可能是汽车数据库-乍一看,您可能会认为牌照可以用作钥匙。但是可以更改这些内容,所以这不是一个好主意。发布应用程序后,您真的不想发现这一点,当有人来找您想知道为什么他们不能将其车牌更改为闪亮的个性化新车时。


2
不幸的是,汽车确实具有不会改变的自然钥匙:VIN(至少在美国是这样)
jcollum

@jcollum是的,这很公平。虽然我的意见仍然成立,但我的榜样并不一定像它可能的那样好。
Mark Embling,2009年

3
当您基于ISO代码时,语言列表将是自然键的示例。因此,如果您随后想要以某种特定的语言从表中加载内容,则无需加入languages表中,因为表中已经存在语言代码(ID)texts
DanMan

1
@DanMan我必须在那里同意你的看法。总是会有一些使用自然键更好地工作的示例。规则或通用方法永远都不是绝对的,这就是我将100%
采纳

5

始终使用单列,如果可能的话,使用替代键。这使联接以及插入/更新/删除操作更加简洁,因为您仅负责跟踪一条信息以维护记录。

然后,根据需要,将您的业务密钥堆叠为唯一的约束或索引。这将使您保持数据完整性。

业务逻辑/自然键可以更改,但是表的物理键绝不能更改。


4

在数据仓库场景中,我认为最好遵循代理密钥路径。两个原因:

  • 您独立于源系统,并且那里的更改(例如数据类型更改)不会影响您。
  • 您的DW将需要较少的物理空间,因为您将仅使用整数数据类型作为代理键。同样,您的索引将更好地工作。

3

情况1:您的表是具有少于50种类型(插入)的查找表

使用业务/自然键。例如:

Table: JOB with 50 inserts
CODE (primary key)       NAME               DESCRIPTION
PRG                      PROGRAMMER         A programmer is writing code
MNG                      MANAGER            A manager is doing whatever
CLN                      CLEANER            A cleaner cleans
...............
joined with
Table: PEOPLE with 100000 inserts

foreign key JOBCODE in table PEOPLE
looks at
primary key CODE in table JOB

情况2:您的表是具有数千个插入

使用代理/自动增量键。例如:

Table: ASSIGNMENT with 1000000 inserts
joined with
Table: PEOPLE with 100000 inserts

foreign key PEOPLEID in table ASSIGNMENT
looks at
primary key ID in table PEOPLE (autoincrement)

在第一种情况下:

  • 您可以选择表PEOPLE中的所有程序员,而无需使用表JOB的联接,而只需:“ SELECT * FROM PEOPLE WHERE JOBCODE ='PRG'”

在第二种情况下:

  • 您的数据库查询速度更快,因为您的主键是整数
  • 您无需费心寻找下一个唯一密钥,因为数据库本身为您提供了下一个自动增量。

2

当业务信息可以更改或相同时,代理键可能很有用。毕竟,公司名称不必在全国范围内唯一。假设您与两家名为Smith Electronics的公司打交道,一家在堪萨斯州,另一家在密歇根州。您可以通过地址来区分它们,但是那会改变。甚至状态也可以改变。如果堪萨斯州堪萨斯城的史密斯电子公司过河而过,到密苏里州堪萨斯城怎么办?没有明显的方法可以使这些业务与自然密钥信息区分开,因此代理密钥非常有用。

将代理密钥想像成一个ISBN号。通常,您通过书名和作者来识别一本书。但是,我有两本HP Willmott题为“珍珠港”的书,它们绝对是不同的书,而不仅仅是不同的版本。在这种情况下,我可以参考书籍的外观,或者参考早期的书籍,还是参考后来的书籍,但是我也可以参考ISBN。


1
我想我不得不不同意你在这里的例子。ISBN号是一本书的属性。代理键与其余行数据无关,因此,即使ISBN已经唯一标识每本书,该位置仍主张为书本表使用单独的代理键。
Christopher Cashell

或者,将ISBN视为代理密钥本身。这是一个没有意义的标识符,只是应用于特定书籍的代码。如果您要制作书籍表,则ISBN也可能是主键(假设您每行总是有一本书)。
David Thornley,2010年

@Christopher Cashell-一年前出现在这篇文章中,但我想添加一些内容。ISBN不能保证是唯一的,并且可以重复。我有一个朋友在图书馆工作了很多年,他们经常碰到带有重复ISBN的书籍,问题在于ISBN的唯一性是发行人的责任,而不是一个机构来确保所有出版物的所有数字是独一无二的,而这些发布者并不一定总是在一起行动。
托马斯

2
从一年前开始浏览此帖子,并想提到ISBN实际上是自然键。与代理键不同,含义本身包含在键值中。例如,部分密钥标识发布者。另外,如上所述,我们不能保证它们是唯一的。它们本来应该是唯一的,但是唯一性来自出版商,而且它们并不总是完美的。
托马斯(Thomas)

从技术上讲,公司不能在州之间移动。发生的事情是在新的州创建了一家新公司,并转移了资产。这也适用于数据库信息。
沃伦·露

2

提醒一下,将聚簇索引放在随机代理键(即读取XY8D7-DFD8S的GUID)上不是一个好习惯,因为它们的SQL Server无法对这些数据进行物理排序。您应该改为在这些数据上放置唯一索引,尽管简单地对主表操作运行SQL事件探查器,然后将这些数据放入数据库引擎优化顾问也可能会有所帮助。

参见线程@ http://social.msdn.microsoft.com/Forums/en-us/sqlgetstarted/thread/27bd9c77-ec31-44f1-ab7f-bd2cb13129be


我很确定SQL Server可以对GUID进行排序。
迈克尔·格林

这是不准确的,尽管他们可以评估GUID,但得出的结果对人类而言并非没有道理。stackoverflow.com/questions/7810602/…–
布赖恩·斯旺

1
正确的说法,但与“ SQL Server无法对它们进行物理排序”大不相同。
Michael Green

2

这是代理键几乎总是有意义的情况之一。在某些情况下,您要么选择最适合数据库的对象,要么选择最适合对象模型的对象,但是在两种情况下,使用无意义的键或GUID都是一个更好的主意。它使索引编制变得更加容易和快捷,并且它是您的对象的不变标识。


1

马课程。陈述我的偏见;我首先是一名开发人员,所以我主要关心的是为用户提供有效的应用程序。

我已经在使用自然键的系统上工作,并且不得不花费大量时间来确保价值变化会不断蔓延。

我在只有代理键的系统上工作,唯一的缺点是缺少用于分区的非规范化数据。

我曾与之合作的大多数传统PL / SQL开发人员都不喜欢代理键,因为每个连接的表数量很多,但是我们的测试和生产数据库从未冒过汗。多余的联接不会影响应用程序性能。对于不支持诸如“ Xa = Xb上的X内部联接Y”之类的子句的数据库方言,或者不使用该语法的开发人员,替代键的额外联接确实使查询更难阅读,并且键入和查询的时间更长。检查:请参阅@Tony Andrews帖子。但是,如果您使用ORM或任何其他SQL生成框架,您将不会注意到它。触摸输入也可以缓解。


也; 如果您想真正驱使代理键就是那个,请从一个随机的大数字开始,然后将序列增加3+而不是1。或者使用相同的序列为多个键生成值。
WillC 2012年

1

也许与该主题不完全相关,但是我在处理代理密钥时感到头疼。Oracle预交付的分析会在仓库中的所有维度表上创建自动生成的SK,并且还会将它们存储在事实中。因此,每当添加新列或为维度中的所有项目填充时,都需要重新加载它们(维度),更新期间分配的SK使SK与存储在事实中的原始值不同步,从而迫使完全重新加载所有加入它的事实表。我希望即使SK是一个无意义的数字,在某种程度上也不会更改原始/旧记录。众所周知,开箱即用的产品很少能满足组织的需求,我们必须不断进行定制。现在我们的仓库中有3年的数据,而且从Oracle Financial系统完成的重新加载非常大。因此,就我而言,它们不是从数据输入生成的,而是添加在仓库中以帮助报告性能。我明白了,但是我们的确改变了,这是一场噩梦。


0

对于时间点数据库,最好将代理键和自然键组合在一起。例如,您需要跟踪俱乐部的会员信息。成员的某些属性永远不变。例如出生日期,但姓名可以更改。因此,使用member_id代理键创建一个Member表,并为DOB创建一列。创建另一个名为人员名的表,并在member_id,member_fname,member_lname,date_updated的列中添加列。在此表中,自然键为member_id + date_updated。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.