GUID作为主键-离线OLTP

5
我们正在设计一个典型的OLTP应用程序(比如:采购系统)。然而,这个特定的应用程序需要一些用户脱机工作,因此他们需要能够将数据库下载到本地计算机上进行操作,然后在局域网上同步回来。
我想指出的是,我知道这已经被做过了,我只是没有使用过这个特定的模型。
我考虑过的一个想法是使用GUID作为表键。例如,采购订单不会有一个数字(自动编号),而是一个GUID,以便每个脱机客户端都可以生成它们,并且当我重新连接到数据库时不会发生冲突。
这是一个不好的想法吗?通过GUID键访问这些表会很慢吗?
您是否有这些类型系统的经验?您是如何解决这个问题的?
谢谢! 丹尼尔
15个回答

8
使用Guid作为主键是可以接受的,出于与您考虑相同的原因,这被认为是一种相当标准的做法。但它们可能会被过度使用,这可能会使调试和管理变得有点乏味,因此请尽可能将它们排除在代码表和其他参考数据之外。
你必须关注的是可读性标识符。Guids不能由人交换 - 你能想象通过电话确认你的订单号如果是一个guid吗?因此,在离线场景下,你仍然可能需要生成某些东西 - 如发布者(工作站/用户)ID和一些序列号,所以订单号可能是123-5678 -。
然而,这可能无法满足业务要求,例如一些监管要求(如SOX)要求发票号必须是连续的。在这种情况下,可能需要生成一种类似于形式化编号的编号,稍后在系统同步时进行修正。您可能会得到具有OrderId(Guid),OrderNo(int),ProformaOrderNo(varchar)的表 - 这可能会引入一些复杂性。
至少使用Guid作为主键意味着当同步最终发生时,你不必进行大量级联更新 - 你只需更新可读的数字即可。

我想再补充一点:将你的GUID进行Base64编码可以解决大部分的可读性问题。 - NotMe
22个字符对于手机检查来说仍然太长了,我认为。 - Anton Tykhyy
1
微软的产品密钥/认证代码真是让人头疼,他们似乎并不这么认为。通过电话读出来真是太麻烦了! - davewasthere

3

@SqlMenace

GUID存在其他问题,因为GUID不是顺序的,所以插入将分散在各处,这会导致页面分裂和索引碎片化。

这并不完全正确。 主键!=聚集索引。

如果聚集索引是另一列(例如“inserted_on”),则插入将是顺序的,并且不会发生页面分裂或过度碎片化。


请注意,如果inserted_on不是唯一的,SQL Server将在聚集索引(幕后)添加一些“唯一化”的额外字节。此外,请注意,created_on可能会生成碎片,因为行可以按照与客户端中创建时不同的顺序插入到聚集索引中。虽然不确定这是否适用于OPs问题,但对于已同步的数据库,需要注意这一点。 - Christian Davén

2
这是使用GUID的完美案例。唯一的缺点可能是在使用GUIDs时稍微复杂一些,以及大小上的略微差异(16字节 vs 4字节)。
我认为这两个问题都不是很大的问题。

1

我只是想指向Sequential Guid相对于标准Guid的性能改进是什么?,它涵盖了GUID的讨论。

为了人类可读性,考虑分配机器ID,然后使用这些机器的顺序号作为可能性。这将需要管理机器ID的分配,可以在一列或两列中完成。

我个人喜欢SGUID的答案。


1
通过GUID密钥访问这些表会很慢吗?
GUID存在其他问题,因为GUID不是顺序的,所以插入将分散在各个地方,这会导致页面分裂和索引碎片化。
在SQL Server 2005中,微软引入了NEWSEQUENTIALID()来解决这个问题,但你可能唯一的问题是只能将NEWSEQUENTIALID用作表中的默认值。

你和Portman都有合理的观点。GUIDS是一把非常锋利的双刃剑。 - Namphibian

1

你说得没错,这是一个老问题,有两个经典的解决方案:

  • 使用唯一标识符作为主键。请注意,如果您关心可读性,可以自己生成唯一标识符而不是使用GUID。唯一标识符将使用日期和机器信息生成唯一值。

  • 使用“Actor”+标识符的复合键。每个用户都有一个数字演员ID,并且新插入行的键使用演员ID以及下一个可用标识符。因此,如果两个演员都使用ID“100”插入新行,则不会违反主键约束。

就我个人而言,我更喜欢第一种方法,因为我认为复合键作为外键真的很繁琐。我认为人类可读性的抱怨被夸大了——最终用户无论如何都不需要知道您的键的任何信息!


1

确保使用guid.comb - 它会处理索引问题。如果在此之后您遇到性能问题,那么很快您将成为扩展方面的专家。

使用GUID的另一个原因是为了实现数据库重构。假设您决定对Customers实体应用多态性或继承等功能。现在,您希望Customers和Employees从Person派生,并共享一个表。拥有真正独特的标识符使数据迁移变得简单。没有序列或整数标识字段需要处理。


0

使用GUID键肯定比标准整数键慢(并且占用更多内存),但这是否是一个问题取决于您的系统将承受的负载类型。根据您后端DB的不同,索引GUID字段可能存在问题。

使用GUID简化了一整类问题,但代价是部分性能和调试能力——在那些测试查询中输入GUID会变得老套。


0
后端将使用 SQL Server 2005
前端/应用逻辑将使用 .Net

除了 GUIDs,你能想到其他解决离线计算机同步新数据回中央数据库时发生的"合并"的方法吗?我的意思是,如果键是整数(INTs),基本上在导入时就必须重新编号。使用 GUID 可以避免这种情况。


0

使用GUID在我们需要将两个数据库合并成一个时,节省了我们大量的工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接