Maximware 发表于 2013-1-4 01:26:04

再谈数据库主键选取策略

<div id="cnblogs_post_body">INT和GUID,究竟选谁?

关于数据库主键的选取策略,大家都是在INT和GUID两者中徘徊。忘了那些喋喋不休的争论吧!毕竟鱼与熊掌,不可兼得。在这篇文章中,我们不再关注它们的优缺点,自觉先行做点功课哦!
如小标题,如果真要选,我会选谁?肯定地说,我会选GUID,又或者两者都选上。后者情形下,使用GUID做主键、INT做小二,INT在业务层生成,这要即使重复了,也不碍事,且INT是要反馈给前端的,定时做一个防冲突检测。如果让用户记忆或反馈那GUID字符串(去连接字符后32位),可以直接去跳楼了!
INT和GUID,究竟谁快?

使用INT或GUID做主健,究竟谁更快?为回答这个问题,我们先看下面的表格内容:
                                    主键类型                                       字段类型                                       存储长度(字节)                                                         Int                                       int                                       4                                                         Int                                       bigint                                       8                                                         GUID                                       uniqueidentifier                                       16                                                         GUID                                       char(36)                                       36                                                         GUID                                       varchar(36)                                       36+4=40                                                         GUID                                       nchar(36)                                       36x2=72                                                         GUID                                       nvarchar(36)                                       36x2+4=76                         解释一下:
   
[*]uniqueidentifier存储为二进制值,为什么是16字节呢?0~f 共16 种表示,有16*16=256,也有2^8=256(值域为0~255),去掉四个连接字符,即表示为16字节。   
[*]varchar和nvarchar属变长型,存储时会增加一个int类型(四个字节)记录内容长度。   
[*]nchar和nvarchar类型存储为Unicode数据,占用两个字节,所以字节数要算双份。
谁会更快?
   
[*]勿庸置疑,INT肯定是最快的,甚至你会选择int而不是bigint。   
[*]其次,谁会更快?当选uniqueidentifier。   
[*]项目中,选用了varchar、nchar、nvarchar中某一类型?只怕你会是神,不是人或妖。
INT和GUID,谁主沉浮?

项目中,如果你是使用INT做主健,那么接下来的内容可以直接略过?因为你已经得到了答案。
写这篇随笔的主要目的,是要告诉大家,使用GUID做主键时,特别要注意索引与排序问题。
GUID做主键,字段类型为char(36),数据记录索引与排序依据肯定是字符串的从左到右,即:12345678-0000-0000-0000-000000000000
GUID做主键,字段类型为uniqueidentifier,数据记录索引与排序依据将是后六字节,即:00000000-0000-0000-0000-1234567890ab
为什么会这样?数据存储为uniqueidentifier时,会体现为SqlGuid 结构。
MSDN描述有:SqlGuid使用 SQL Server行为实现CompareTo,该行为只计算值的最后6个字节。Guid 计算全部 16 个字节。
结束语

为了验证所说,你可以这样做:建表并添加uniqueidentifier字段类型,随机插入几万条记录,然后观察后十二位字符的排序情况,或参考下面截图。
http://www.panson.cn/AttachFile/UploadFile/Image/20120728/11f0040a-8672-47d3-aaac-8499dc883b6e.png
补充说明

29号补充:大家可以看看SQL SERVER 2005中新增的NEWSEQUENTIALID()函数,参考MSDN中链接http://msdn.microsoft.com/zh-cn/library/ms189786.aspx。不管你信不信,它的后六字节是有序列的(字符串的后12位)。
参考网文

   
[*]   NEWSEQUENTIALID() (Transact-SQL)   
[*]SqlGuid 结构描述   
[*]比较 GUID 和 uniqueidentifier 值 (ADO.NET)   
[*]小议数据库主键选取策略(原创)   
[*]反驳 吕震宇的“小议数据库主键选取策略(原创)”   
[*]再议《反驳 吕震宇的“小议数据库主键选取策略(原创)” 》   
[*]我也来谈谈对主键的看法(把主键进行分类)   
[*]使用Guid做主键和int做主键性能比较   
[*]数据库中使用自增量字段与Guid字段作主键的性能对比
盘诚原创,随笔同步链接:http://www.panson.cn/Archive/11f0040b-e660-4b99-8ba2-60a13630bea7.html
页: [1]
查看完整版本: 再谈数据库主键选取策略