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 / 问题 / 232120
Accepted
igelr
igelr
Asked: 2019-03-15 03:22:10 +0800 CST2019-03-15 03:22:10 +0800 CST 2019-03-15 03:22:10 +0800 CST

如何为同一数据库的不同表生成全局唯一ID?

  • 772

在 SQL Server 上的生产系统中,所有表中的所有 id(主要是 PK)都是自动生成的,并且我被告知它们是全球唯一的。我的意思是数据库中没有 2 个 id 相同,即使表不同。我想知道如何做到这一点?如果有多种方式,请全部列出。谢谢。

sql-server unique-constraint
  • 3 3 个回答
  • 7700 Views

3 个回答

  • Voted
  1. Best Answer
    Michael Green
    2019-03-15T03:34:52+08:002019-03-15T03:34:52+08:00

    回到那天,我们有一张ID桌子。单列,单行,有一个int值。每个事务首先更新该表以获得一个新值,然后在需要的地方使用该值。当然,这是并发错误的一个重要来源。

    后来,引入了序列。在整个数据库中使用的单个序列将显示您描述的行为。文档中有一个示例说明了这一点:

    CREATE TABLE Audit.ProcessEvents
    (
        EventID int DEFAULT (NEXT VALUE FOR Audit.EventCounter), -- same sequence, different table
        <other columns>
    );
    
    CREATE TABLE Audit.ErrorEvents
    (
        EventID int DEFAULT (NEXT VALUE FOR Audit.EventCounter), -- same sequence, different tables
        <other columns>
    );
    
    

    我编辑了示例以突出显示此用法。

    通过在应用程序代码中生成全局唯一编号,然后将它们传递到数据库,可以获得相同的结果。如果我要实现它,我想它会作为编译到可执行文件中的某个实用程序类的静态方法(尽管其他实现是可能的)。假设应用程序需要将客户的详细信息写入数据库。由于它正在编组客户姓名、地址、电话号码等,它还会生成一个新的全局 ID。ID 仅作为另一个参数值传递给 INSERT 语句(或存储过程)。

    ID 值是由应用程序架构层还是数据库层产生的,取决于具体的设计考虑。如果应用程序可以横向扩展实例之间的协调就会出现问题。应用程序重新启动后,代码必须找出下一个要使用的值。数据库服务器已经将这些功能和其他功能写入其中。

    我绝对不会让应用程序只为下一个 ID 调用数据库,然后将其与业务数据一起编组到 INSERT 中。当只需要一次时,到数据库的往返次数太多了。

    • 13
  2. David Spillett
    2019-03-15T04:15:11+08:002019-03-15T04:15:11+08:00

    对于同一张表中的唯一 ID 值,我假设您知道常用的IDENTITY选项,通常使用从 1 开始的 32 位值(因此以这种方式定义 PK 类似于ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY)。BIGINT如果表可能需要超过 2,147,483,647 行,您当然可以使用更大的 ( )。

    SQL Server 可以选择定义自己的序列,该序列可以在多个表之间共享,可能是所有表。有关详细信息,请参阅https://learn.microsoft.com/en-us/sql/t-sql/statements/create-sequence-transact-sql。然后,您将每个 ID 列定义为ID INTEGER DEFAULT NEXT VALUE FOR The_sequence_You_Defined PRIMARY KEY。不过,这里有一些事情需要注意。与IDENTITY您不同的是,不会阻止删除任何旧值(即不存在的值),因为默认情况下仅在未明确给出序列值时应用序列值,这可能是有问题的。此外,使用序列的执行速度会稍慢一些,并且可能会成为瓶颈,因为所有表都依赖于同一个对象,尽管这两个问题只有在您的数据库在短时间内看到大量插入活动时才会引起关注。NEXT VALUE FOR The_sequence_You_Defined也可以在其他地方使用(即SET @someVariable = NEXT VALUE FOR The_sequence_You_Defined;),这意味着如果您需要在应用程序逻辑的其他地方生成 ID,您可以通过这种方式完成(事实上,我已经看到它甚至用于单个身份,而不仅仅是共享序列多个对象之间)。

    一个更 hacky 的方法可能是BIGINT对每个身份列使用 a,并从(例如)4,000,000,000 的不同倍数开始。这将在其他数据库中工作并避免瓶颈问题,但确实会使密钥大小增加一倍,并且如果您不小心定义了两个 ID 从同一点开始的表,则可能会给您带来维护噩梦。您可能希望添加检查约束以确保以这种方式定义的标识值不会溢出到另一个值的数字空间中,这会增加一些性能问题。

    如果您不介意较大的键,那么UUID很有用,并且具有在数据库(所有数据库,顾名思义)之间唯一的额外优势,而不仅仅是在一个数据库中的表之间。与序列一样,这些都与默认约束一起应用,即ID UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT NEWID(). 不过,这些是 128 位值,BITINT是“标准”32 位大小的两倍和四倍INTEGER。如果您担心由 v4 UUID 的随机性引起的额外碎片的可能性,您可以使用它NEWSEQUENTIALID()而不是NEWID()仍然足够独特(在这个星系的生命周期中发生碰撞的机会非常小)。

    • 7
  3. kovalensue
    2019-03-15T03:54:43+08:002019-03-15T03:54:43+08:00

    首先,我不得不提一下,我没有使用 SQL Server,所以我不能指出一些具体的功能。

    我有两个关于如何做到这一点的概念:

    1. 一个顺序来统治它们:这个概念听起来很简单。您有一个序列负责为插入到任何表的每一行生成 ID。在我上一份工作中,我们使用了这个概念。实施取决于很多情况,所以我会让你决定。但一种方法是有一些存储过程,它将在任何插入之前检索序列的下一个值。
    2. 时间戳:您可以以某种方式将时间戳合并到您的 ID 中

    在 SQL Server 世界中,您可以参考: NEWID() 文档- newid 符合RFC4122

    • 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