标识列或UDF显式生成唯一ID?


11

我正在就是否最好PRIMARY KEY使用Identity Columns(我们明确使用生成唯一ID的UDF)进行辩论。

  • 我在为“身份栏”争论。
  • 他说,我的搭档正在争吵手动生成值
    • 通过将UDF放在另一个可以放置UDF的桌子上
      • 锁定资源
      • 用一个称为ID_Value的字段递增ID表1
      • 使用它作为全局唯一标识符
    • 或者id+1在插入时让表格做一个
    • 在没有标识约束的服务器和/或环境之间移动数据更容易;从一个有数据的数据库移动到另一个具有类似暂存数据或虚拟数据的类似数据库。对于非生产中的测试,我们可能希望将昨天的所有记录拉到暂存阶段进行测试。

哪种实现更有意义?

Answers:


21

你的同事是个白痴。

该解决方案将无法扩展,UDF不是并发的(与此相同的原因)。以及如何处理多行插入:这将要求每行调用UDF

而且在现实生活中迁移到其他RDBMS的情况并不常见……您最好现在不使用SQL Server,而在Oracle上使用序列,并希望您不要迁移。

编辑:

您的更新指出,移动数据用于刷新非生产数据库。

在这种情况下,刷新时将忽略标识列。您不会牺牲您的实现以简化非产品加载。或使用临时表来跟踪标识值的更改。

或使用流程:我们每天晚上从生产中刷新测试系统,从而完全避免了该问题。(并确保我们的产品备份也可以还原)


11

使用标识值。生成自己的序列表和序列值将花费大量开销,并在尝试生成数字时导致大量锁定和阻塞。

身份存在是有原因的,请使用它。

当SQL Denali发布时,它将支持比身份更有效的序列,但是您自己无法创建更有效的序列。

至于将记录从一种环境移动到另一种环境,请在插入时打开IDENTITY_INSERT或在SSIS中选中该框。


如果您从“生产”转移到“测试”并具有一个标识字段,则可能会覆盖或碰撞数据。我就是这么说 是的,这不应该成为一个问题方向,但我只是说,它可能发生。
jcolebrand

没错,在dev,test,qa,uat和production中,不同行值的编号相同。所以呢?如果这些值很重要(例如对于查找表),则手动对其进行硬编码,这不成问题,因为您不应该经常在这些表中放置值。如果您需要控制环境之间的标识值以避免冲突,那么从生产中恢复时,请重置环境之间的标识值。
mrdenny

5

身份列对我来说听起来不错。我不确定我为什么要在服务器之间移动数据很困难的逻辑。

如果您确实希望每行都具有全局唯一身份,则可以使用UUID,但除非您确定必须具有全局唯一性,否则我不会这样做-通常不是。将UUID用作ID会降低性能,增加磁盘空间要求并增加调试难度-由于篇幅太长,很难记住UUID,很难通过电话告诉UUID或将其写在纸上而不会出错。


4

对于简单的数字ID,只需加上标识即可,而无需手动生成它们的所有问题。

您始终可以创建一个使用身份作为PK并具有类型列和任何其他信息的“超级表”。当您需要一个新的ID(假设您是指不同表中唯一的IDS)时,只需将其插入此表中并抓取SCOPE_IDENTITY(),然后再插入所需的实际表中即可。

基本上,您需要创建一个表:具有身份PK的MasterID,当您需要在Table1中插入一行,INSERT INTO MasterIDs并使用该值生成该行生成的身份SCOPE_IDENTITY(),然后使用该值作为PK 插入到Table1中

表1将具有一个不相同的int PK。您将执行相同的过程以将其插入到Table2等中。让SQL Server管理MasterIDs表中的标识值,然后可以在其他表中使用该标识值。 MasterID可以包含其他表,例如类型(因此您可以知道哪个表,Table1或Table2等使用该标识值。


3

只要您正确使用外键约束(级联,更新等),那么使用身份字段就可以了。在这种情况下,我真的看不到其他解决方案的优势。


2

进行身份验证以适合您的情况。您拥有诸如用于服务器/环境数据交换的复制之类的工具,可以将它们全部保持在一起。


1

我刚刚完成了一项工作,其中我将SQL Server identity列替换为普通int字段并自己控制了ID分配。

我已经看到了相当可观的性能提升。与OP不同,我没有UDF来生成ID。但是原理几乎是相同的:该软件的一部分维护着一组ID。当它们用完时,它将通过查询数据库中的下一个Low值来获取另一批并将其递增到下一个High

这使我们能够在将批处理提交到数据库之前生成ID并关联ORM中事务之外的所有实体,然后再将批处理提交到数据库,并且无需进行额外的往返操作即可提交更大的批处理以获取刚刚插入的标识(标识列要求)。

在id表中,我们有不止一行,如果需要,我们可以使用特定范围。即用于重用已删除的块和否定ID。


0

我使用身份已有多年,并认真考虑用UNIQUEIDENTIFIER替换身份号码。如果有人将数据类型设计为紧凑型数据库,则需要更改数据类型,这是一场噩梦;如果您需要向列中添加身份,则是噩梦,同样,您也无法更新身份列。想象一下,您将一个int数据存储到了20亿条记录,而噩梦又改变了(考虑FK)!除非使用bigint,否则更改带有身份的任何内容都是一场噩梦,并且不便于扩展。UNIQUEIDENTIFIER vs Identity =便利性和鲁棒性,也许还有显着的性能改进(没有进行基准测试)。

更新:看到这一点后,我肯定会倾向于UNIQUEIDENTIFIER。这没有显示bigint身份的真正好处,也没有为UNIQUEIDENTIFIER带来很多好处!不同版本的SQL Server可能会有不同的结果。在所有数据库和系统上都有唯一的ID只是很美(稳健)!根据需要移动,复制,转换数据! https://www.mssqltips.com/sqlservertip/5105/sql-server-performance-comparison-int-versus-guid/


64位INT将持续很长一段时间...
Vérace
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.