分片数据库(Azure联合数据库)的ID生成

7
我一直在寻找有关Azure联合数据库的id生成最佳实践的文章或指导,但没有找到令人信服的内容。 联合表不支持标识列,因此在我看来,唯一实用的id类型是GUID,因为尝试集中创建和使用BigInt会在应用程序中创建单点故障。 我最担心的是在索引表时使用GUID相对于BigInt的性能影响。
是否有任何推荐/最佳实践(或现有库)可为分布式系统创建唯一的BigInt(或者我不必担心使用GUID的性能影响?)。
[更新]
阅读了发布问题后更多的相关内容,我认为在Azure中密钥生成将是一个问题。根据微软的blog文章建议,使用GUID作为联合密钥。然而,他们没有提到联合表上的所有索引(包括聚集索引)都必须包含联合密钥。这意味着所有这些索引都将包含一个GUID,这将影响插入性能。
另一种选择似乎是使用集中式密钥生成服务(如Simon所提到的),但这也有其缺点,可能成为潜在瓶颈和故障中心。
我本以为微软会对此提供更多指导,因为毕竟这是创建联合表时每个人都会面临的问题!
综合考虑,我决定使用集中式密钥生成服务,但这让我有点担心。如果有任何神奇的技巧,我很想听听(或者让我知道我是否错过了一些明显的东西)!
4个回答

4
你可以使用多种技术在应用程序中创建序列,但由于其分布式特性,这并不是一件容易的事情。其中一种相当好的方法是使用Blob存储和前提条件
根据您的项目进度,您可能希望使用SQL 2012 SEQUENCE,并将所有序列放入一个小型的非联合数据库中。SEQUENCE目前尚不可用于SQL Azure。

2
当考虑到联合密钥时,重要的是要考虑一个能够在联合成员之间实现良好分布的密钥,因此在许多情况下,生成的 ID 不是一个好主意。例如,按订单 ID 进行分区将意味着所有最新的订单都在最新的联合成员中,并且很可能是大多数用户正在操作的成员,因此联合的好处将大大降低;而按国家/客户 ID 等进行分区更有可能实现联合旨在带来的可扩展性优势。
当涉及到行的唯一标识时,需要考虑到实体将存储在不同的数据库中,因此无法使用身份或序列生成。请查看 Cihan Biyikoglu 的博客文章 - 他的建议是使用 uniqueidentifier 或 datetimeoffset。

1
在我的项目中,我总是使用GUID作为联合键,因为我认为它不会造成巨大的性能问题。也许我的项目不是那么庞大,但对我来说确实有效。所以我对你的第一个问题的答案是“是”。
至于你的下一个问题,我正在考虑在那里设置一个ID生成器服务,就像你想的那样,但是是的,它可能会成为瓶颈。我在想如果我们可以有一个ID池,利用一些分布式缓存来存储由此服务生成的ID。这样,任何想要ID的人都可以从池中检索,而不是按需生成。因此,ID生成器将继续将ID推入该池中,消费者将从中弹出ID。这可能会有所帮助,但是再次说明,我从未以这种方式实现过,因此可能无法确定它是否是最佳实践。
希望这有所帮助。

0

使用GUID作为主键的一个负面影响是,如果表在主键上聚集,则插入操作会导致大量页面分裂。这是因为好的GUID不是按照时间顺序生成的,以便难以猜测。

Azure SQL表确实需要聚集索引。我的建议是在基于范围的值(如日期时间)上有一个聚集索引,并使用非聚集索引作为主键,该主键将是GUID。


3
抱歉,@Lucifure,这种方法行不通,因为联合键必须包含在任何聚集索引中... 这是Azure联邦表的限制。 - Mike Hanrahan
@Mike,将主键添加到聚集索引中不起作用吗? 因此,例如,聚集索引是datetime+PK,而PK本身又是另一个索引。 - hocho
如果我理解你所建议的,我认为那不起作用,因为另一个限制是联合密钥必须包括在任何唯一索引(以及集群索引)中。由于PK本身将成为另一个唯一索引,我不认为有任何有效使用GUID的方法。这里有关于这些限制的更多详细信息:http://msdn.microsoft.com/en-us/library/windowsazure/hh597469.aspx。 - Mike Hanrahan

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