使用代理密钥系统,大多数常用引擎(MS SQL Server,Oracle,DB2,MySQL等)不会遇到明显的问题。有些人甚至可以通过使用代理来提高性能,但是性能问题是特定于平台的。
一般而言,自然键(以及扩展为复合键)的替代键辩论历史悠久,几乎看不到“正确答案”。
自然键(单数或复合键)的参数通常包括以下内容:
1) 它们已经在数据模型中可用。已建模的大多数实体已经包括一个或多个属性或属性组合,这些属性可以满足创建关系所需的键需求。向每个表添加其他属性会合并不必要的冗余。
2) 他们消除了某些联接的需要。例如,如果您的客户具有客户代码,发票具有发票编号(两者都是“自然”键),并且想要检索特定客户代码的所有发票编号,则可以简单地使用"SELECT InvoiceNumber FROM Invoice WHERE CustomerCode = 'XYZ123'"
。在经典的代理键方法中,SQL看起来像这样:"SELECT Invoice.InvoiceNumber FROM Invoice INNER JOIN Customer ON Invoice.CustomerID = Customer.CustomerID WHERE Customer.CustomerCode = 'XYZ123'"
。
3) 它们为数据建模提供了一种更为通用的方法。使用自然键,可以在不同的SQL引擎之间大体上不变地使用相同的设计。许多代理密钥方法使用特定的SQL引擎技术来生成密钥,因此需要对数据模型进行更多专业化处理才能在不同平台上实现。
代理键的争论通常围绕SQL引擎特定的问题展开:
1) 当业务需求/规则更改时,它们使属性更改更容易。这是因为它们允许将数据属性隔离到单个表中。对于没有有效实现标准SQL结构(例如DOMAIN)的SQL引擎,这主要是一个问题。当通过DOMAIN语句定义属性时,可以使用ALTER DOMAIN语句在架构范围内对属性进行更改。不同的SQL引擎对于更改域具有不同的性能特征,并且某些SQL引擎根本不实现DOMAINS,因此数据建模人员通过添加代理键来提高这些属性的能力,从而弥补了这些情况。
2) 与自然键相比,它们使并发的实现更容易。在自然键情况下,如果两个用户同时使用相同的信息集(例如客户行),并且其中一个用户修改了自然键值,则第二个用户的更新将失败,因为他们是客户代码数据库中不再存在更新。在代理键的情况下,更新将成功处理,因为不可变的ID值用于标识数据库中的行,而不是可变的客户代码。但是,并非总是希望允许第二次更新-如果客户代码已更改,则由于该行的实际“身份”已更改,可能不应该允许第二个用户继续进行更改-第二个用户可能更新错误的行。代理键或自然键都无法单独解决此问题。
3) 它们的性能比自然键好。性能最直接受到SQL引擎的影响。由于SQL引擎的数据存储和检索机制,在使用不同SQL引擎的同一硬件上实现的同一数据库架构通常会具有截然不同的性能特征。一些SQL引擎非常接近平面文件系统,当相同的属性(例如客户代码)出现在数据库架构的多个位置时,实际上将冗余存储数据。当需要对数据或架构进行更改时,SQL引擎的这种冗余存储会导致性能问题。其他SQL引擎在数据模型与存储/检索系统之间提供了更好的隔离,从而可以更快地更改数据和架构。
4) 代理键在某些数据访问库和GUI框架中的功能更好。由于大多数代理键设计的同类性质(例如:所有关系键都是整数),数据访问库,ORM和GUI框架可以使用该信息,而无需对数据有特殊的了解。由于自然键的异构性质(不同的数据类型,大小等),自然键在自动或半自动工具箱和库中无法正常工作。对于诸如嵌入式SQL数据库之类的特殊方案,可以在考虑特定工具箱的情况下设计数据库。在其他情况下,数据库是企业信息资源,可以由多个平台,应用程序,报表系统和设备同时访问,因此在着重于任何特定库或框架的情况下,数据库也无法正常运行。此外,
我倾向于倾向于自然键(显然),但是我并不狂热。由于我所处的环境,我帮助设计的任何给定数据库都可能被各种应用程序使用,因此我将自然键用于大多数数据建模,而很少引入替代方法。但是,我不会竭尽全力尝试重新实现使用代理的现有数据库。代理密钥系统可以正常工作-无需更改已经运行良好的功能。
有一些出色的资源讨论了每种方法的优点:
http://www.google.com/search?q=natural+key+surrogate+key
http://www.agiledata.org/essays/keys.html
http://www.informationweek.com/news/software/bi/201806814