随笔-7  评论-24  文章-102  trackbacks-0

推荐文章:
http://tech.ddvip.com/2008-10/122517676785777_4.html

使用GUID作为数据库主键的测试
http://www.cnblogs.com/chiname/articles/227584.html



使用uniqueidentifier还是IDENTITY生成主键?

  问题 

  我正在设计一张表,并且决定创建一个自动生成主键值而不是创建自己的模式或者使用自然键。我知道SQL Server提供了全球唯一识别码(GUID),也提供了创建这些值的标识符。请问这些方法有哪些优缺点呢
?

  专家解答

  确实,你可以通过很多种方法来为你的表自动生成主键值。最常见的一种方法是通过使用IDENTITY字段属性,或者指定带有默认NEWID() 或NEWSEQUENTIALID()函数的唯一识别码数据类型。此外,在SQL Server复制中,全球唯一识别码经常被用在带有更新订阅的合并复制或者事务复制的唯一识别符行中



  NEWID()和NEWSEQUENTIALID()有什么区别呢
? NEWID()随机生成一个基于服务器网卡的标识符号码和CPU块唯一号码的保证的唯一值。与此相反,NEWSEQUENTIALID()按照顺序生成这些值而不是随机生成。

  正如你看到的,第一张表使用NEWID()生成随机值而第二张表使用NEWSEQUENTIALID()生成有顺序的值。由于没有通过IDENTITY方法生成整数,生成的全球唯一识别码值看起来在工作中不易于使用。这是另一个要注意的地方。SQL Server在内存中保存最后一个生成的标识值,这样可以在通过使用SCOPE_IDENTITY(),@@IDENTITY或者CHECK_IDENT(取决于你要求的范围)的INSERT语句之后,重新找到这个标识值。这与获得最后一个全球唯一标识符值没有任何相似之处。如果你使用一个全球唯一标识符,你必须创建自己的机制来获得最后一个插入值(比如,在插入之前重新找到全球唯一标识符或者使用SQL Server 2005 OUTPUT从句)




    存储效果

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

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


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

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

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

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

  l 数据库规模最小化。

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

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



使用GUID作为数据库主键的测试

可以看出在以GUID作为主键的表中加一个时间类型或是Int类型的索引可以弥补以GUID作为主键带来的性能损失。

3、这样做是为了模拟现实使用情况,当然这样很片面,因为在平时使用过程中,经常用到分页,计算数据总数,目的是看看在如果在表中不另外加索引会不会影响计算效率,看来用GUID作为主键必须要另外加索引才能保证入count这样的计算不至于消耗太多时间,但是用int类型好像就不会消耗太多时间的,所以这样一比较就看出,如果用varchar字段类型做主键的表,表内一定需要个非聚集索引。 

posted on 2010-04-20 11:52 黄小二 阅读(1494) 评论(0)  编辑  收藏 所属分类: [DB]

只有注册用户登录后才能发表评论。


网站导航: