2014-02-20 52 views
4

我试图在SQL Server中创建一个ID列,VB.net会为数据库中创建的每一个新行提供一系列数字。所以我用下面的技术来创建ID列。使用INT或GUID作为主键

select * from T_Users 
ALTER TABLE T_Users  
ADD User_ID INT NOT NULL IDENTITY(1,1) Primary Key 

然后我注册了几个用户名到数据库中,它工作得很好。例如前六行将是1,2,3,4,5,6。然后我在下一天注册了4个用户,但是这次ID号从6跳到了一个非常大的数字,例如:1,2,3,4,5,6,1002,1003,1004,1005。然后两天后,我又注册了两个用户,新行读取了3002,3004个。所以我的问题是为什么我每隔一天跳过如此大量的注册用户。我用来创建序列的技巧是否错误?如果有任何错误,请告诉我如何做到这一点?现在,当我对上面使用的技术感到沮丧时,或者我尝试使用按顺序生成的GUID值。生成的GUID值序列正常。然而,唯一的缺点是,它会产生很长的数字(4倍的INT大小)。我的问题在于使用GUID是否比INT有任何显着的优势?

问候,

回答

4

上行的GUID:

GUID是好的,如果你想脱机客户能够创造新的纪录,因为你永远不会得到一个主键冲突时,新的记录是同步的回到主数据库。

的GUID的缺点:

GUIDS作为主键可以对数据库的性能产生影响,因为对于一个聚集主键,DB将要保留的行中的键值的顺序。但是这意味着现有记录之间插入很多,因为GUID是随机的。

使用IDENTITY列不会因此受到影响,因为下一个记录保证具有最高值,所以每次只在最后加上一行。不需要重新洗牌。

有一个妥协办法是生成一个伪GUID,这意味着你会期望每隔70年左右发生一次关键冲突,但是却非常有助于索引。

的其他方面的不足是一个),他们确实会占用更多的存储空间,和b)编写针对SQL输入UPDATE TABLE SET FIELD = 'value' where KEY = 50003UPDATE TABLE SET FIELD = 'value' where KEY = '{F820094C-A2A2-49cb-BDA7-549543BB4B2C}'

你的IDENTITY列长相声明一个真正的痛苦,即更容易对我好。关键值中的空白可能是由于尝试添加行失败所致。 IDENTITY值将递增,但该行永远不会被提交。不要让它困扰你,它几乎发生在每个桌子上。

编辑:

这个问题涉及什么我被伪GUID意义。 INSERTs with sequential GUID key on clustered index not significantly faster

在SQL Server 2005+中,您可以使用NEWSEQUENTIALID()来获得应该比前一个值更大的随机值。在这里获取更多信息http://technet.microsoft.com/en-us/library/ms189786%28v=sql.90%29.aspx

+1

诀窍与PK不集群,但东西,而不是群集化确实有一个逻辑顺序 - 例如日期戳,名称或其他。 –

+0

DeanOC,感谢您的反馈。这很有帮助。 –

0

我用来创建序列的技术是否错误?

不,如果你的谷歌技能没有任何东西存在。短期看对的 “SQL Server身份跳过值” 会给你回报的TON包括:

SQL Server 2012 column identity increment jumping from 6 to 1000+ on 7th entry

和规范:

Why are there gaps in my IDENTITY column values?

基本上,你错误地认为SQL Server将不优化它的性能访问。身份号码是标记,没有别的,不要假设没有差距请。

特别是:SQL Server预先分配1000个块中的数字,并且 - 如果重新启动服务器(如在工作站上),其余部分将丢失。

http://www.sqlserver-training.com/sequence-breaks-gap-in-numbers-after-restart-sql-server-gap-between-numbers-after-restarting-server/-

如果你手动sqyuence代替(新宁的SQL Server 2012),您可以定义此(预生成)高速缓存的大小,并将其设置为1 - 在当你做略低性能为代价很多插入。

我的问题在这里是否使用GUID比INT有任何显着的优势?

是的。与int相比,你可以使用GUID更多的行。例如,int32限制在大约20亿行。对于我们中有些人来说太低(我有100亿的桌子),甚至64个大的int也是有限的。而一个真正的zetabyte数据库,你必须依次使用一个guid,自己生成。

任何正常人都没有看到差异,因为我们都没有真正处理那么多行。而更大的尺寸会让很多事情变慢(更大的关键尺寸=指数中更大的空间=更大的指数=对于相同的操作,更多的内存/ io)。再加上你的序列号也会跳。

为什么不只是调整您的期望变为现实 - 身份并不意味着是无间隙 - 或使用序列与缓存1.

+1

简单,杀手!还有比这更糟糕的问题。 ;) – DeanOC

+2

嗨TomTom,首先,最让我说,感谢您的反馈意见。在我半读过你的评论后,我对你描述你的想法的方式感到有些紧张,几乎想停止阅读。相信我,我是Google做出的一个很好的回答,但是如果你没有在Google中写出正确的单词,你并不总是找到你正在寻找的答案。所以它不像我没有Google。因此,有时候我们如何回答问题可能会阻止人们提问,并且会挫败像使用计算器这样的网站的目的。无论如何,感谢您的帮助。 –