为分布式环境选择适宜的主键 (Sync Services)

对于参与增量同步的表,Sync Services for ADO.NET 要求唯一地标识每一行。(对于客户端与服务器快照同步,这不是必需的。)通常,行由服务器或对等数据库中定义的主键进行标识。在分布式环境中,在选择用作主键的列的类型时,必须特别小心谨慎。主键在所有节点上必须是唯一的,而且一定不能重复使用:即使删除了某行,也不应将该行的主键用于其他行。如果在多个节点上使用了同一个主键,便会产生主键冲突。对于任何类型的分布式环境来说这都是一个问题,而不仅仅限于 Sync Services。本主题介绍在选择主键时的若干选择,并且介绍了它们对于分布式环境的适用性。

自动递增(标识)列

数据库架构设计师们经常选择某个自动递增列作为主键。这种自动递增属性(SQL Server 中的 IDENTITY 属性)可为插入表中的每条记录生成一个新值。此新值是通过将当前值(种子)增加或减小固定的值(增量)并将结果赋给要插入的行来产生的。通常,自动递增列使用紧凑数据类型,例如整数。这可能会导致一个更加紧凑的聚集索引、更有效的联接以及在查询基础表时更少的 IO 操作。

但是,由于种子和递增属性是固定的,而且只能从有限的可能值中选择,因此发生主键冲突的可能性非常大。这种类型的主键适合于仅限下载的数据缓存应用情景。在这些应用情景中,服务器或指定的对等方应该是生成新主键值的唯一节点。因此,可以保证这些值在拓扑中的所有节点上都是唯一的。此外,如果只在一个节点上执行插入操作,自动递增列还适合仅限上载应用情景和双向同步应用情景。在这些应用情景中,插入操作通常只发生在服务器或指定的对等方上;而更新操作(可能还有删除操作)则发生在一个或多个客户端上。如果需要在多个节点上执行插入操作,应该使用本主题后面介绍的其他方法之一。

GUID

使用 GUID(SQL Server 中的 uniqueidentifier 列)作为主键可保证主键在任意数量的节点中的唯一性,并消除自动递增列可能出现的主键冲突问题。但是,在主键中使用 GUID 具有以下后果:

  • 大型数据类型(16 字节)增加了聚集索引的大小,这可能对某些常见操作(如联接)造成负面影响。

  • GUID 的无序生成会导致将行插入到聚集索引中的随机位置。这反过来又会导致聚集索引产生碎片。这会对查询基础表所需的 IO 造成不利影响。

    在 SQL Server 2005 和更高版本中,可以使用 NEWSEQUENTIALID() 函数有序地生成 GUID,以帮助消除可能产生的碎片。

包括节点标识符的主键

在这种方法中,使用的主键将服务器或客户端节点上唯一的值与拓扑中唯一的值结合在一起。例如,在客户端与服务器同步中,可以结合使用一个自动递增列(在节点上是唯一的)和一个存储 Sync Services 分配给每个客户端的 ID 的散列值的列。(即在整个拓扑中都保持唯一的 ClientId。)然后,创建一个包含这两个列的复合主键。或者,可以开发一个系统来为每个插入的行生成值,将行 ID 和客户端 ID 包括在一个列中。

自然主键

使用这种策略时,不使用任何类型的生成的主键,而是使用可唯一标识记录的某个业务键。例如,用于存储客户信息的表可以使用身份证号码列作为主键,而不是使用某个标识列。这种方法的缺点是:如果需要使用多个列来唯一地标识记录,主键可能变得很大。此外,这种复合主键必须传播到其他表以支持一个或多个外键关系。而这些关系又会对联接性能造成不利影响。

联机插入

如果前面的解决办法都不适合您,而且您的应用情景只需要在客户端上执行很少的插入操作,对于应用程序来说,直接在服务器上插入这些行可能是最简单易行的方法。然后,在下次同步期间,新行将被下载和插入到客户端上。由于在服务器上生成主键值,因此不会产生主键冲突。

请参阅

概念

应用程序设计和部署注意事项 (Sync Services)