Sql Server identity VS uniqueidentifier

最常见的一个自动生成主键的方法:

  1. IDENTITY属性把原始的种子值当作它第一个参数,把增量值当作它第二个参数值

  2. 把你的字段指定为唯一标识符的类型和使用NEWID() 或者NEWSEQUENTIALID()函数的DEFAULT约束,若字段指定为唯一标识符的类型,则DEFAULT约束必须用来把一个全球唯一标识符分配给这个字段NewID()

  Identity与 uniqueidentifier的区别:

  a.  全球唯一识别码值看起来在工作中不易于使用.SQL Server在内存中保存最后一个生成的标识值,这样可以在通过使用SCOPE_IDENTITY(),@@IDENTITY或者CHECK_IDENT(取决 

   于你要求的范围)的INSERT语句之后,重新找到这个标识值.而如果你使用一个全球唯一标识符,你必须创建自己的机制来获得最后一个插入值(比如,在插入之前重新找到全球唯一标识符   

   或者使用SQL Server 2005 OUTPUT从句)。

  b. 可用下列语句查出数据在数据库中的物理存储:

    SELECTOBJECT_NAME([OBJECT_ID])astablename,avg_fragmentation_in_percent,fragment_count,page_count
    FROMsys.dm_db_index_physical_stats(DB_ID(),null,null,null,null)
    ORDERBYtablename
    GO

    用此语句查出来可得到:NEWID()测试表是成碎片的,因为它的碎片比例是98%。你可以看到这些行分散在490页中。这是因为生成主键的随机属性导致了页拆分。IDENTITY 和NEWSEQUENTIALID()测试表只有极小的碎片比例,这是因为它们按照特定顺序自动生成键。结果使它们免受页拆分之苦,而使用NEWID()方法具有页拆分的困扰。尽管你可以用磁盘碎片整理程序处理NEWID()表,但是主键产生的随机属性仍然会由于将来对表做插入操作而引起页拆分和碎片。尽管如此,页拆分仍然可以通过指定恰当的FILL FACTOR而减到最小。

  通过观察NEWSEQUENTIALID()测试表,我们不难发现它产生的页数比NEWID()方法产生的少,但仍然比IDENTITY方法产生的多。这是为什么呢?这是因为唯一标识符数据类型消耗16字节的磁盘空间,而不是像IDENTITY方法那样只使用4个字节的整数数据类型。考虑到SQL Server页通常限制在8K或者大约8060字节(因为在SQL Server 2005中有一种行溢出机制来解决这个问题,不过这是题外话),这造成的后果是:

  NEWSEQUENTIALID()方法产生更多的页而不是IDENTITY方法产生更多的页。

  通过查看使用的数据库表空间,我们看到使用IDENTITY方法的表使用最少量的磁盘空间:

  execsp_spaceusedIDENTITY_TEST1
  GO
  execsp_spaceusedIDENTITY_TEST2
  GO
  execsp_spaceusedIDENTITY_TEST3
  GO
  execsp_spaceusedNEWID_TEST
  GO
  execsp_spaceusedNEWSEQUENTIALID_TEST
  GO

  现在也来考虑这个问题,因为唯一标识符数据类型消耗16字节的数据,任何在一张表中使用一个全球唯一识别码作为聚集索引的定义非聚集索引大小都会受到影响,因为这些非聚集索引的叶级别包含作为指示器的聚集索引键。因此,如果一个IDENTITY被定义为整数或者bigint数据类型,那么任何非聚集索引的大小可能会因为比较大而终止。

  很明显,使用IDENTITY来自动生成键值比使用全球唯一标识符方法更具有优势:

  1. IDENTITY生成值是可以配置的,并且易于阅读,易于在工作中使用。

  2. 可以使用更少的数据库页来满足查询请求。

  3. 与NEWID()方法相比,它在页拆分(与前面相关)方面的担忧可以消除。

  4. 数据库规模最小化。

  5. 存在系统函数来获得最后生成的IDENTITY值(比如SCOPE_IDENTITY()等)

  6. 一些系统函数,比如MIN()和MAX(),不能在唯一标识符字段中使用。

原文地址:https://www.cnblogs.com/lilycnblogs/p/1653898.html