AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 274919
Accepted
oopoopoop
oopoopoop
Asked: 2020-09-04 07:40:41 +0800 CST2020-09-04 07:40:41 +0800 CST 2020-09-04 07:40:41 +0800 CST

我应该将前端生成的 UUIDv6 转换为 binary(16) 以在 SQL Server 中用作集群主键吗?

  • 772

背景

根据前端开发人员的建议,我研究了在我们的新系统中使用 UUID 作为一堆表的主键。从学习随机 UUID 与顺序 UUID 的优缺点,到结合使用非聚集主键和可排序类型的聚集索引,我的研究向我指出了UUIDv6及其实现。

它能够生成如下所示的 UUID(即顺序的):

UUIDv1 UUIDv6 
---------------------------------- -------------- ---------------------- 
5714f720-1268-11e7-a24b-96d95aa38c32 1e712685-714f-6720-a23a-c90103f70be6 
68f820c0-1268-11e7-a24b-96d95aa38c32 1e712686-8f82-60c0-ac07-7d6641ed230d 
7ada38f0-1268-11e7-a24b-96d95aa38c32 1e712687-ada3-68f0-93f8-c1ebf8e6fc8c 
8cc06fd0-1268-11e7-a24b-96d95aa38c32 1e712688-cc06-6fd0-a828-671acd892c6a 
9ea6a6b0-1268-11e7-a24b-96d95aa38c32 1e712689-ea6a-66b0-910c-dbcdb07df7a4

我认为 SQL Server 会很乐意在集群主键(唯一标识符)列中为我排序。

我几乎不知道 SQL Server 如何对 uniqueidentifier 列进行排序。这是升序排序结果:

UUIDv6 唯一标识符已排序 
---------------------------------- 
1e712688-cc06-6fd0- a828-67  1acd892c6a
1e712686-8f82-60c0- ac07-7d  6641ed230d
1e712687-ada3-68f0-93f8- c1 ebf8e6fc8c 
1e712685-714f-6720-a23a- c9 0103f70be6 
1e712689-ea6a-66b0-910c- db cdb07df7a4

这会导致碎片,就像使用随机 UUID 一样。这篇文章解释了它们实际上是如何排序的。

真正的问题

幸运的是,该系统仍在开发中。接下来我应该选择哪些选项?

  1. 重新排序字节,使最高/最低有效字节位于 SQL Server 期望的位置
UUIDv6 UUIDv6 重新排序的字节 
---------------------------------- -------------- ---------------------- 
1e712685-714f-6720-a23a-c90103f70be6 c90103f7-0be6-a23a-6720- 1e712685 714f 
1e712686-8f82-60c0-ac07-7d6641ed230d 7d6641ed-230d-ac07-60c0- 1e712686 8f82 
1e712687-ada3-68f0-93f8-c1ebf8e6fc8c c1ebf8e6-fc8c-93f8-68f0- 1e712687 ada3 
1e712688-cc06-6fd0-a828-671acd892c6a 671acd89-2c6a-a828-6fd0- 1e712688 cc06 
1e712689-ea6a-66b0-910c-dbcdb07df7a4 dbcdb07d-f7a4-910c- 66b0-1e712689 ea6a
  1. 将 UUIDv6 转换为二进制(16)并改用它
UUIDv6 UUIDv6 二进制(16) 
---------------------------------- -------------- ------------------ 
1e712685-714f-6720-a23a-c90103f70be6 1e712685 714f6720a23ac90103f70be6 
1e712686-8f82-60c0-ac07-7d6641ed230d 1e712686 8f8260c0ac077d6641ed230d 
1e712687-ada3-68f0-93f8-c1ebf8e6fc8c 1e712687 ada368f093f8c1ebf8e6fc8c 
1e712688-cc06-6fd0-a828-671acd892c6a 1e712688 cc066fd0a828671a ​​cd892c6a 
1e712689-ea6a-66b0-910c-dbcdb07df7a4 1e712689 ea6a66b0910cdbcdb07df7a4

有问题option 1

UUID 标准在 ID 中嵌入了一个 4 位版本字段。UUIDv6(仍然是非标准的)也遵循该规则。我将重新排序它们的方式将打破这一点。

有问题option 2

我不确定。除了这个,几乎找不到任何人在谈论它,这与这个想法背道而驰。在使用 binary(16) 类型时我还应该注意其他陷阱吗?

谢谢!

sql-server uuid
  • 3 3 个回答
  • 374 Views

3 个回答

  • Voted
  1. Josh Darnell
    2020-09-04T09:16:19+08:002020-09-04T09:16:19+08:00

    我会考虑另一种选择:在代理键(如Id int IDENTITY(1,1) NOT NULL)上进行集群,并使应用程序生成的 UUID 成为非集群主键。

    这避免了您使用选项 1 和 2 调用的问题,因为您不必担心基表中的排序/碎片问题,或者集群上潜在的深奥问题binary。

    它还会为您节省一些空间(int 小于uniqueidentifierand binary(16)),因为集群键包含在每个非聚集索引中(以及通过外键引用该表的其他表)。

    • 6
  2. Joe Obbish
    2020-09-09T10:14:23+08:002020-09-09T10:14:23+08:00

    我在 SQL Server 中使用过 BINARY 数据类型,但不记得我是否曾经在 BINARY 列上创建过带有聚集索引的表。话虽如此,我知道唯一需要注意的是文档中的这个注释:

    不保证任何数据类型和二进制数据类型之间的转换在 SQL Server 版本之间是相同的。

    如果您确实使用选项 2,我建议在应用程序代码中在 SQL Server 之外对 BINARY 值进行所有转换和操作。

    • 3
  3. Best Answer
    David Browne - Microsoft
    2020-09-09T12:03:38+08:002020-09-09T12:03:38+08:00

    重新排序字节,使最高/最低有效字节位于 SQL Server 期望的位置

    去做。

    选项 1 是 SQL Server 原生使用 NEWSEQUENTIALID() 所做的,正如维基百科所说

    NEWSEQUENTIALID 函数返回类似于 UUID 的 128 位标识符,这些标识符承诺按顺序升序,直到下次系统重新启动

    在 SQL Server 中,UNIQUEIDENTIFIER 只是一个 128 位二进制类型。它不需要符合 UUID 的结构。

    如果它是按顺序生成的*,您可以将其设为聚集索引键。拥有一个更窄的聚集索引键通常不值得拥有一个额外且不必要的索引的成本。

    *如果顺序值的排序顺序中的位置偶尔发生变化或由几个不同的应用程序服务器在几个不同的地方生成,这不是什么大问题。

    • 3

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve