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 / 问题 / 29116
Accepted
DamagedGoods
DamagedGoods
Asked: 2012-11-23 05:18:07 +0800 CST2012-11-23 05:18:07 +0800 CST 2012-11-23 05:18:07 +0800 CST

使用增量为 -1 的 IDENTITY 列

  • 772

我需要运行一个 sql server logging db,其中 2 个主表在 2 个单独的数据中心同时写入这两个数据中心。

我的想法是将数据库恢复到新的数据中心,然后将标识列重新设置为 -1 并将增量设置为 -1,这样当需要组合数据时就不会出现重复的 id。DATACENTRE1 是正整数,DATACENTRE2 是负整数

-1 的增量会导致任何问题吗?

sql-server database-design
  • 6 6 个回答
  • 10769 Views

6 个回答

  • Voted
  1. Best Answer
    Aaron Bertrand
    2012-11-23T08:45:11+08:002012-11-23T08:45:11+08:00

    倒退对我来说是错误的。

    只有两个数据中心,您还可以实施身份范围。除非您以惊人的速度循环浏览身份值,否则您没有理由不能拥有:

    -- Data center 1
    CREATE TABLE dbo.Table
    (
      ID INT IDENTITY(1,1) PRIMARY KEY
      -- , ...
    );
    
    -- Data center 2
    CREATE TABLE dbo.Table
    (
      ID INT IDENTITY(1000000000,1) PRIMARY KEY
      -- , ...
    );
    

    这将允许在与数据中心 2 发生冲突之前在数据中心 1 中生成 10 亿个(嗯,999,999,999)个值。您可以在数据中心 1 中添加一个 CHECK 约束以防止重叠值,具体取决于您的优先级错误与重复。如果您担心在应用程序的生命周期中任何一个数据中心确实会产生超过十亿个值(没关系你的)。

    如果约 10 亿还不够,还有另外两种选择可以提供更多喘息空间:

    -- Data center 1
      ID INT IDENTITY(-2147483648,1)
    
    -- Data center 2
      ID INT IDENTITY(1,1)
    

    这将为每个数据中心提供超过 20 亿个非重叠值,在数据中心 1 接近 0 之前没有碰撞危险。如果这还不够:

    -- Data center 1
      ID BIGINT IDENTITY(-9223372036854775808,1)
    
    -- Data center 2
      ID BIGINT IDENTITY(1,1)
    

    或者,如果您想保持所有值 > 0,您可以将正数范围大致分成两半(如果您比我更迂腐,您可以比这更精确一些)。

    -- Data center 1
      ID BIGINT IDENTITY(1,1)
    
    -- Data center 2
      ID BIGINT IDENTITY(4611600000000000000,1)
    

    我什至不知道怎么说这个数字,但它是巨大的。实际上,当您的曾曾曾曾孙从大学毕业时,您必须在一台速度非常快的计算机上非常努力地使用所有这些值。如果您使用的是企业版,则可以使用数据压缩,这样您就不必为所有 8 个字节付出代价,至少在数据中心 1 中,直到那里的数据量超过 20 亿。


    在我管理的一个系统中,我采用了稍微不同的方式——我们有多个带有 Express 实例的 Web 服务器,它们负责生成需要在企业中唯一的 ID 号。所以我们只是在每台机器上设置了一个序列生成器(它们不需要实际存储值),使用 BIGINT IDENTITY 列。我们有 < 9 台服务器,所以它们都是这样播种的:

    -- WEBAPP0001
    ID BIGINT IDENTITY(10000000000,1)
    
    -- WEBAPP0002
    ID BIGINT IDENTITY(20000000000,1)
    
    -- WEBAPP0003
    ID BIGINT IDENTITY(30000000000,1)
    
    ...
    

    当使用这些值然后在中央系统中合并时,我们不仅可以保证没有任何重复,而且还可以很容易地立即识别它们来自哪个 Web 服务器(这有时在调试中很有用),而无需引入任何复合关键要求。我们也不担心任何一台 Web 服务器会产生超过 100 亿的价值。

    在这种情况下,很多人会使用 GUID,但我认为有几个强烈的论据反对这种方法。

    • 9
  2. Stuart Moore
    2012-11-23T05:37:14+08:002012-11-23T05:37:14+08:00

    它不会导致问题,因为 SQL Server 允许您这样做:

    
    create table decrement(
    id integer identity(0,-1),
    test int
    )
    
    insert into decrement (test) select number from numbers
    
    select top 10 id, test from decrement order by id asc
    go
    id  test
    ------------
    -5103   5110
    -5102   5109
    -5101   5108
    -5100   5107
    -5099   5106
    -5098   5105
    -5097   5104
    -5096   5103
    -5095   5102
    -5094   5101
    

    但从长远来看,一个好主意可能是一个不同的问题。其他人可能最终会感到困惑(即;我不得不考虑上面查询的顺序,因为它与正常情况相反)。或者当其他人恢复数据库并IDENTITY以“正常”方式重新设置种子并且您的 ID 重叠时会发生什么?

    是否可以修改您的架构,以便您拥有一个“站点”列?那么使用站点和ID作为组合键呢?

    • 7
  3. ypercubeᵀᴹ
    2012-11-23T07:12:58+08:002012-11-23T07:12:58+08:00

    使用此设置可能会出现一些问题:

    按照@Martin Smith评论中的链接,标识列中的负值可能会导致某些应用程序出现问题:为什么数据库设计人员不让标识列从最小值而不是 1 开始?

    另一个问题与值是否为负但正在减少无关,以及标识是否也是表的聚集键。当从左到右(从低到高)遍历以及在右侧(高)侧完成插入时,例如当键不断增加时,B-tree 结构更有效。这个属性对于表的聚集键更加重要。请参阅Kimberly Tripp的这篇博客文章,了解集群键的最佳属性,尤其是关于不断增加的.

    使用递减键,您将始终在索引的错误(左侧)插入数据,从而导致索引碎片。这些影响可能对您的情况并不重要,但我认为如果身份也被选为集群密钥,您应该牢记这一点。

    或者正如@Martin 建议的那样,将聚集索引也定义为DESC(-1)数据中心。这将避免上述任何碎片问题。


    实现相同功能并保持增加 ID 的其他选项是在一个数据中心中具有偶数值,而在另一个数据中心中具有奇数值(因此两者都具有 +2 增量)或siteID添加到主键,如@Stuart 建议的那样。

    • 7
  4. marc_s
    2012-11-23T05:35:19+08:002012-11-23T05:35:19+08:00

    去尝试一下!(然后在这里报告:-))。

    不,我预计不会有任何问题 - 毕竟,INT的数据范围是 -20 亿到 +20 亿 - 我不明白为什么负数的行为应该与正IDENTITY数有任何不同......

    • 3
  5. James Page
    2015-10-10T07:19:56+08:002015-10-10T07:19:56+08:00

    这听起来像是按键数据分区的一种变体。另一种方法是使用种子和增量,以便每个数据中心生成交错但不冲突的值。尝试类似:

    DC #1: IDENTITY (1, 2)
    DC #2: IDENTITY (2, 2)
    

    每个表中的标识值都有差距:

    DC #1 has values: 1, 3, 5, ...
    DC #2 has values: 2, 4, 6, ...
    

    如果您认为您将来可能有额外的 DC,请将增量设置为您可能拥有的 DC 数量(例如 4)。滚入时,您将拥有:

    DC #1: IDENTITY ( 1, 4)
    DC #2: IDENTITY ( 2, 4)
    DC #3: IDENTITY ( 3, 4)
    DC #4: IDENTITY ( 4, 4)
    
    • 3
  6. BillThor
    2012-11-23T16:54:29+08:002012-11-23T16:54:29+08:00

    我使用的方法是:

    • 为每个服务器启动一个顺序值,并以大于预期服务器数量的值递增。
    • 为每个服务器使用不同的范围。
    • 对两台服务器使用通用序列。

    每个解决方案都有优点和缺点。

    • 1

相关问题

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

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

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

  • 在数据仓库中实现多对多关系有哪些方法?

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

Sidebar

Stats

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

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

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

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

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

    • 4 个回答
  • Marko Smith

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

    • 7 个回答
  • 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
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +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
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +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