使用数据库时,通常使用某种id字段为表中的每一行提供唯一标识符。
例如,想象一个customers表。例如,我们不希望使用名称或地址等字段作为唯一标识符,因为可能有多个客户具有相同的名称或共享相同的地址。
相反,最好为每一行分配某种唯一标识符。我们有一个选择是使用UUID。
什么是UUID?
UUID是通用唯一标识符的缩写,顺便提一下,它是一个36个字符的字母数字字符串,可以用来标识信息(例如表行)。
以下是UUID的一个示例:acde070d-8c4c-4f0d-9d8a-162843c10333
UUID被广泛使用的部分原因是,它们很可能在全球范围内是唯一的,这意味着不仅我们的行的UUID在数据库表中是唯一的,而且它可能是任何系统中唯一一个具有该UUID的行。
(从技术上讲,我们生成的同一个UUID可以在其他地方使用并非不可能,但如果有340282366920938463463374607431768211456个不同的可能的UUID,可能性非常小)。
UUID为什么存在?
为了回答这个问题,让我们假设我们正在经营一家电子商务书店。当订单进入时,我们希望为其分配一个id号,并使用该编号将其存储在订单表中。
我们可以设置顺序ID,使第一个顺序为1,第二个顺序为2,依此类推:
如果我们的规模较小,这种方法可能会很好地工作,至少在一段时间内是这样。然而,它有一些主要的缺点:
首先,当我们连接表或导入新数据时,它很容易造成混淆,因为上面的id值不是唯一的。即使我们对多个表使用相同的ID系统,这也会在内部产生问题,但当我们开始处理任何类型的外部数据时,它确实会变得一团糟。
例如,想象一下,我们的小书店在增长,我们收购了另一家在线书店。当我们去整合订单表时,我们发现它们使用了相同的系统。现在我们有两个1阶,两个2阶,等等,为了解决这个问题,我们必须更新我们正在集成的两个数据库中至少一个数据库中的每个ID。即使在最好的情况下,这也将是一个巨大的麻烦。
其次,顺序方法在任何类型的分布式系统中都不能很好地工作,因为它意味着插入命令必须逐个执行。这种限制可能会导致大规模的性能问题。即使您的应用程序需要严格的ID排序,使用功能也可能允许您满足这些要求,同时仍然使用UUID,并且不会受到顺序排序ID带来的性能影响。
唯一ID的其他传统方法,例如使用串行生成随机ID,也可能导致分布式系统中的热点,因为大约在同一时间生成的值具有相似的值,因此在表的存储中彼此靠近。
UUID解决了所有这些问题,因为:
它们是全局唯一的,因此即使在外部数据中也会遇到重复ID的机会非常小。它们可以在不需要检查中心节点的情况下生成,因此在分布式系统中,每个节点都可以自主生成UUID,而不必担心重复或一致性问题。
原因#1本身就是在几乎任何数据库系统中使用UUID的一个很好的理由。作为一家渴望大规模运营的企业,reason#2与我们的书店也非常相关,因为分布式数据库提供了最佳的可扩展性和弹性。
UUID的缺点
UUID唯一的显著缺点是它们在内存中占用128位(当我们包含元数据时,通常会占用更多)。如果最小化存储空间是绝对关键的任务,那么清楚地存储顺序ID(可能在1-10个数字字符之间)将比存储36个字符的字母数字更有效。
然而,在大多数情况下,使用序列标识符之类的东西的缺点大大超过了使用UUID带来的存储成本的最小增加。UUID非常流行,广泛用于各种不同的识别目的。本文重点介绍了数据库示例,因为UUID也用于分析系统、web和移动应用程序等。
UUID的类型
有几种不同类型的UUID:
版本1和版本2。有时称为基于时间的UUID,这些ID是使用日期时间值(反映生成UUID的时间)、随机值和生成UUID的设备的一部分MAC地址的组合生成的。
下面是它在视觉上的分解:
以这种方式生成UUID几乎不可能具有相同的UUID——它们必须由同一设备在完全相同的时间生成,并且生成完全相同的随机16位序列。
因为它们包含生成设备MAC地址的一部分,所以UUID v1和UUID v2 ID可用于识别(例如)哪个数据库节点生成了ID。这通常不是问题,在分布式系统中,这可能是一个优势。
(v1和v2 UUID之间的区别在于,UUID v2还包含本地域号的一段。由于许多原因,这使得它们在大多数应用程序中不太理想,因此UUID v2没有被广泛使用。)
版本3和版本5。这两个版本的UUID是通过哈希命名空间标识符和名称生成的。它们类似于基于时间的uuid,因为它们是使用现有数据生成的,而不是完全随机的,而是使用名称空间数据和名称数据,而不是使用日期时间数据和设备MAC地址。
名称空间数据本身就是一个UUID,名称数据实际上可以是任何任意字符串,尽管在实践中,它通常与UUID的使用方式有关——例如,它可能是一个帐户名称或产品ID。但无论使用的两个值是什么,它们都会被散列以生成一个36个字符的字母数字字符串,这是最终的UUID。
UUID版本3和5的主要区别在于它们使用不同的哈希算法。UUID v3使用MD5,UUID v5使用SHA-1。
版本4。这些UUID只是随机生成的36个字符串。除了表示它们是v4 UUID的单个4之外,每个字符都只是a-z中的随机字符或0-9中的整数。
因为生成完全是随机的,所以它们极有可能是唯一的。它们也不包含诸如日期时间、MAC地址或名称数据之类的标识信息(这可能是优点或缺点,取决于特定用例)。
版本6、7和8。截至撰写本文时,这些版本均不存在,但它们已被提出,并可能在未来几年添加到UUID标准中。您可以在这里阅读更多关于这些提议的新UUID的信息。
以这种方式生成UUID几乎不可能具有相同的UUID——它们必须由同一设备在完全相同的时间生成,并且生成完全相同的随机16位序列。
因为它们包含生成设备MAC地址的一部分,所以UUID v1和UUID v2 ID可用于识别(例如)哪个数据库节点生成了ID。这通常不是问题,在分布式系统中,这可能是一个优势。
(v1和v2 UUID之间的区别在于,UUID v2还包含本地域号的一段。由于许多原因,这使得它们在大多数应用程序中不太理想,因此UUID v2没有被广泛使用。)
版本3和版本5。这两个版本的UUID是通过哈希命名空间标识符和名称生成的。它们类似于基于时间的uuid,因为它们是使用现有数据生成的,而不是完全随机的,而是使用名称空间数据和名称数据,而不是使用日期时间数据和设备MAC地址。
名称空间数据本身就是一个UUID,名称数据实际上可以是任何任意字符串,尽管在实践中,它通常与UUID的使用方式有关——例如,它可能是一个帐户名称或产品ID。但无论使用的两个值是什么,它们都会被散列以生成一个36个字符的字母数字字符串,这是最终的UUID。
UUID版本3和5的主要区别在于它们使用不同的哈希算法。UUID v3使用MD5,UUID v5使用SHA-1。
版本4。这些UUID只是随机生成的36个字符串。除了表示它们是v4 UUID的单个4之外,每个字符都只是a-z中的随机字符或0-9中的整数。
因为生成完全是随机的,所以它们极有可能是唯一的。它们也不包含诸如日期时间、MAC地址或名称数据之类的标识信息(这可能是优点或缺点,取决于特定用例)。
版本6、7和8。截至撰写本文时,这些版本均不存在,但它们已被提出,并可能在未来几年添加到UUID标准中。您可以在这里阅读更多关于这些提议的新UUID的信息。
如何生成UUID
UUID看起来可能很复杂,但在现代应用程序开发环境中,生成它们实际上相当简单。大多数流行的编程语言都有库,使生成UUID像调用函数一样简单。
例如,在Javascript中,只需导入uuid包,然后调用uuid。v1(),以生成UUID v1。Python非常类似:导入并调用uuid。uuid1()生成UUID v1。
数据库,尤其是分布式数据库,也可能具有内置的UUID生成。例如,在CockroachDB中,我们建议使用uuid作为行标识符,这样做就像使用gen\u random\u uuid()函数一样简单。
因此,例如,当我们使用SQL创建表时,我们可以确保它为每一行自动生成UUID v4,如下所示:
CREATE TABLE users (
id UUID NOT NULL DEFAULT gen_random_uuid(),
city STRING NOT NULL,
name STRING NULL,
address STRING NULL,
credit_card STRING NULL,
CONSTRAINT "primary" PRIMARY KEY (city ASC, id ASC),
FAMILY "primary" (id, city, name, address, credit_card)
);
任何时候,在该表中插入一行时,id值都将是自动生成的UUID。
长话短说:生成和使用UUID通常相当简单。具体的实现细节可能会因我们使用的特定数据库技术和/或编程语言而略有不同,但在大多数情况下,它归结起来只不过是调用某种“generate_uuid()”函数。
分布式数据库中的UUID
分布式SQL数据库提供了一个强大的组合:NoSQL数据库的弹性规模和弹性,以及SQL数据库的事务一致性和熟悉性。
然而,使用分布式系统确实意味着需要以不同的方式处理一些事情。如前所述,传统的行ID生成方法,例如通过将1添加到整数来生成序列ID,以便将行标识为2、3、4等,在分布式系统中效果不佳。这些方法会导致“热点”节点,并造成性能瓶颈。
UUID为许多分布式工作负载提供了一种更好的选择,因为数据库中的每个节点都可以自主生成完全唯一的UUID,而不必与其他节点进行检查。
但这并不意味着uuid总是最佳选择。在CockroachDB中,使用UUID通常效果很好,但在某些情况下,使用多列主键可以提供优异的性能(尽管设置和测试也更复杂)。
原文标题:What Is a UUID and Why Should You Care?
原文作者:Charlie Custer
原文链接:https://dzone.com/articles/what-is-a-uuid-and-why-should-you-care