代码之家  ›  专栏  ›  技术社区  ›  Nick

不为主键使用自动递增数字的原因

  •  17
  • Nick  · 技术社区  · 16 年前

    我目前正在处理其他人的数据库,其中的主键是通过一个查找表生成的,该表包含一个表名列表和使用的最后一个主键。存储过程会递增此值,并在将其返回到调用“insert”SP之前检查其唯一性。

    使用这样的方法(或仅生成GUID)而不是仅使用标识/自动编号有什么好处?

    我说的不是真正“意味着”ISBN或产品代码之类的主键,而是唯一标识符。

    谢谢

    16 回复  |  直到 16 年前
        1
  •  27
  •   Galwegian    16 年前

    在您使用复制的情况下,自动生成的ID可能会导致问题(我相信您找到的技术也可以!)。在这些情况下,我通常选择GUID。

        2
  •  19
  •   Greg Smalter    16 年前

    使用自动编号本身并没有什么错,但有几个理由不这么做。不过,正如dacracot所提到的,滚动您自己的解决方案并不是最好的主意。让我解释一下。

    其次,其他数据库不使用这种模式,而Oracle的序列等其他模式则更好。幸运的是,可以使用SQL Server模拟Oracle序列。一种方法是为整个数据库创建一个单独的自动编号表,称为MainSequence,或者其他什么。数据库中没有其他表将使用autonumber,但是需要自动生成主键的任何人都将使用MainSequence来获取它。这样,您就可以获得dacracot所说的所有内置性能、锁定、线程安全等,而无需自己构建。

    另一种选择是使用guid作为主键,但我不建议这样做,因为即使您确信人类(甚至开发人员)永远不会阅读它们,也可能有人会阅读,而且这很难。更重要的是,在T-SQL中,隐式转换为int非常容易,但是隐式转换为GUID会有很多麻烦。基本上,它们是不方便的。

        3
  •  10
  •   Cœur Gustavo Armenta    6 年前

    CodingHorror :

    专业指南

    • 允许轻松合并来自不同数据库的记录
    • 您可以在任何地方生成ID,而不必往返数据库

    GUID Cons

    • 它比传统的4字节索引值大4倍;如果不小心,这可能会对性能和存储造成严重影响
    • 调试繁琐(其中userid='{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')
    • 生成的guid应该是部分顺序的,以获得最佳性能(例如,SQL 2005上的newsequentialid()),并支持使用聚集索引

        4
  •  6
  •   dacracot    16 年前

    递增的过程方法必须是线程安全的。否则,您可能无法获得唯一的号码。此外,它必须快速,否则将成为应用程序瓶颈。内置函数已经考虑了这两个因素。

        5
  •  6
  •   Jon Skeet    16 年前

    对于客户机来说,能够预先分配一大堆ID来执行批量插入,而不必使用插入的ID更新其本地对象,这是非常有用的。然后是整个复制问题,正如Galwegian所提到的。

        6
  •  4
  •   Epidemus Epidemus    16 年前

    以下是使用自动递增整数作为键的情况:

    以上是我的决定因素,是采用一种方法还是另一种方法。

        7
  •  3
  •   Erich Enke Erich Enke    16 年前

    它们没有任何意义

    在我看来,一个主键——除了识别一个记录之外,没有其他存在的理由。如果它没有现实意义,那么它就没有改变的现实理由。一般来说,您不希望主键发生更改,因为您必须搜索并替换整个数据库,或者更糟。我一直很惊讶,我一直认为这类事情是独一无二的,不会改变,但多年后却没有发生。

        8
  •  3
  •   bobwienholt    16 年前

    也许您有一个应用程序,它在多个数据库中收集数据,然后在一天中的不同时间与主数据库“同步”。在这种情况下,您不必担心主键冲突。

        9
  •  2
  •   Corey Trager    16 年前

    一个好处是,它可以使数据库/SQL更加跨平台。SQL Server、Oracle等上的SQL可以完全相同。。。

        10
  •  1
  •   shyam    16 年前

    sequences 都是发明出来的,代码却忘了跟上;)

        11
  •  1
  •   Grank    16 年前

    我更愿意在大多数情况下使用GUID,在这些情况下,post的当前方法对我来说是有意义的(复制是可能的)。如果存在复制问题,那么这样的存储过程必须知道必须链接的另一台服务器,以确保密钥的唯一性,这将使它非常脆弱,而且可能是一种糟糕的方法。
    我使用非自动递增标识的整数主键的一种情况是,很少更改的查找表强制使用外键约束,在数据使用应用程序中将具有相应的枚举。在这种情况下,我希望确保enum映射在开发和部署之间是正确的,特别是在有多个prod服务器的情况下。

        12
  •  1
  •   bobince    16 年前

        13
  •  0
  •   MusiGenesis    16 年前

    GUID PK的缺点之一是GUID字段上的连接速度较慢(除非最近发生了更改)。使用GUID的另一个好处是,尝试向非技术经理解释为什么GUID冲突不太可能发生是很有趣的。

        14
  •  0
  •   Alex    16 年前

    Galwegian的答案未必正确。

    使用MySQL,您可以为每个数据库实例设置密钥偏移量。如果你把它和一个足够大的增量结合起来,它会很好。我相信其他供应商也会有类似的设置。

    increment = 2
    db1 - offset = 1
    db2 - offset = 2
    

    db1将具有键1、3、5、7。。。。

    db2将有键2、4、6、8。。。。

        15
  •  0
  •   Kevin Fairchild    16 年前

    我对自动递增键的主要问题是它们没有任何意义。

        16
  •  -1
  •   BradC    16 年前

    这样做的唯一真正原因是与数据库无关(如果不同的db版本使用不同的自动编号技术)。

    这里提到的另一个问题是在多个地方创建记录的能力(比如在中央办公室以及旅行用户的笔记本电脑上)。不过,在这种情况下,您可能需要像“sitecode”这样的东西,它对于每个ID前面的每个安装都是唯一的。