数据库主键三种唯一标识符比较


本文讨论了在数据库模式中使用自动递增整数键和 UUID 作为主键之间的权衡。
文章提议了第三种专有方案,即时间排序唯一标识符(TSID)。

以下是三种方案总结:

  1. 自动递增整数键方案:具有出色的性能和按时间排序的特点,但不能由多个独立节点生成,而且可能会泄露底层数据的信息。
  2. UUID :提供了唯一的密钥,无需依赖中央机构即可生成,但占用空间更大,性能更差,而且缺乏可读性。
  3. 时间排序唯一标识符(TSID):提供了性能、时间排序和唯一性,同时避免了自动递增整数和 UUID 的缺点,可谓两全其美。

原文摘要:
在设计数据库表结构时,主键或外键是很重要的, 如users.id 和 posts.user_id,而最常见的两种选择是使用自动递增整数类型和通用唯一标识符(UUID)。

在本文中,我们将逐一研究这两种类型,以了解它们之间的利弊,然后研究第三种方案,根据我们的经验,这种方案可提供两全其美的结果:时间排序唯一标识符 (TSID)。我们将解释 TSID 是如何工作的,与其他两种方案相比有哪些优缺点,并看看我们目前在生产系统中使用的 PostgreSQL 中的 TSID 实现。

自动递增
大多数数据库引擎的默认选择是使用整数类型。
大多数 SQL 数据库都有 64 位整数类型,其名称类似于64 位整数类型,其名称类似于BIGINT,使得每个表有2 ^ 63 - 1大约 90亿个可用键。

  • 生成方式: 这种键是一个数据库列,每次插入新记录时,其值会自动增加。通常用于标识记录的顺序和创建顺序。
  • 唯一性: 这种键的唯一性是由数据库管理系统保证的,每个新记录都会自动获得一个比上一个记录更大的整数值。
  • 可读性: 自动递增整数键的值通常是简单的整数,很容易理解和阅读。

使用自动递增整数有几个明显的好处。最基本的好处之一是,它们几乎受到每个 SQL 数据库的本机支持,并且由于其适度的空间需求和顺序整数的出色索引特性,它们很可能具有出色的性能。

原因是数据局部性(部分顺序性),这意味着相似的记录一起存在于磁盘上,从而在许多上下文中允许更高效的数据写入和数据检索。

自动递增整数按时间顺序排序,较新的记录始终比较旧的记录具有更大的值。

自动递增整数是人类可读的。

缺点:

  • 无法全局生成,不能由多个单独的节点串联生成,不适合分布式环境。
  • 安全问题,黑客能推断给定类型中给定类型的记录总数。

UUID通用唯一标识符
UUID 是一个 128 位整数,通常表示为 32 个字符的十六进制字符串,并且通常以 8-4-4-4-12 格式显示

  • 生成方式: UUID是一个128位的数字,通常表示为32个十六进制数字,以及四个连字符,形如 "8-4-4-4-12" 的结构。UUID的生成方式是基于算法和设备信息,具有极低的碰撞概率,因此在分布式系统中广泛使用。
  • 唯一性: UUID的唯一性主要基于其生成算法和包含的信息,保证在全球范围内的唯一性。
  • 可读性: 相对于自增整数,UUID不够直观可读,因为它们是一个长字符串而非简单的数字。

两者比较:

  • 唯一性: UUID具有更高的唯一性,几乎可以保证在全局范围内的唯一性,而自动递增整数键的唯一性仅限于特定数据库表中。
  • 可读性: 自动递增整数键的值更容易理解和记忆,而UUID通常比较长,不太适合直接人工处理。
  • 性能: 自动递增整数键在插入时性能较好,因为数据库可以轻松地预测下一个可用的整数值。而UUID的生成可能涉及到更多的计算和处理,可能对性能有一定影响。
  • 应用场景: UUID常用于分布式系统,或者需要在多个数据库之间确保唯一性的情况。自动递增整数键通常在需要简单标识记录顺序的情况下使用。

UUID 适用于以下场景:

  • 需要唯一标识数据项的场景,例如用户 ID、订单 ID、产品 ID 等。
  • 需要确保数据项安全性的场景,例如密钥、凭证等。

自动递增整数适用于以下场景:
  • 需要对数据项进行排序或查找的场景,例如记录数、分页数等。
  • 需要对数据项进行分页或分段的场景,例如用户列表、订单列表等。

按时间排序的唯一标识符键TSID
它是为实现时间排序标识符而发布的特定规范的名称。结合了Twitter 开发和使用的Snowflake ID和[url=https://github.com/ulid/spec]ULID[/url]的思想。

一些主要功能是:

  • TSID 按时间排序顺序生成(与其他时间排序标识符一样,包括前面提到的 UUIDv7)
  • TSID 是 64 位整数
  • TSID 可以通过Crockford base32 编码表示为 13 个字符的字符串
  • TSID 生成算法可以选择包含节点 ID,以确保在多个源(例如多个数据库或应用程序服务器)生成的 TSID 保持唯一

基本思想之一是 TSID 是按时间排序的,因此它们是自然排序的。当按数字排序时,至少相隔一毫秒生成的 TSID 将始终保持其生成顺序。对于大多数应用程序来说,这是与自动递增整数共享的一个优点。

与 UUID 一样,TSID 也包含随机成分,因此无法提前预测连续生成的 TSID。

缺点是,由于 TSID 生成是高度可配置的,如果需要跨数据库甚至完全不同的系统组件(例如,都需要生成 TSID 的 SQL 数据库和辅助服务)移植,管理配置可能会成为一种负担。每个人都需要维护自己的实施副本,以消除冲突风险)