Sql server GUID集群主键';s比BIGINT和INT-identity PK';SQL Server 2012 Express上有什么?

Sql server GUID集群主键';s比BIGINT和INT-identity PK';SQL Server 2012 Express上有什么?,sql-server,indexing,database-performance,sql-server-2012-express,Sql Server,Indexing,Database Performance,Sql Server 2012 Express,我正在开发一个数据库密集型应用程序,它维护大约5个表。这些表每个都包含数千条记录。所有表都使用GUID群集主键。为了提高效率,我在表之间放置了外键 我正在运行一个65000行长的脚本,该脚本创建了一整组表(包括我的表)和存储过程(大约花费了其中一半的时间),然后继续向我的表中插入大约40000条记录,然后更新大约20000条记录 在我的AMD 3.5 Ghz 8核机器上需要1:15的时间 令人惊讶的是,如果我把这5张桌子改成 -添加BIGINT标识代理主键(查询仍然使用GUID连接) -将先前的

我正在开发一个数据库密集型应用程序,它维护大约5个表。这些表每个都包含数千条记录。所有表都使用GUID群集主键。为了提高效率,我在表之间放置了外键

我正在运行一个65000行长的脚本,该脚本创建了一整组表(包括我的表)和存储过程(大约花费了其中一半的时间),然后继续向我的表中插入大约40000条记录,然后更新大约20000条记录

在我的AMD 3.5 Ghz 8核机器上需要1:15的时间

令人惊讶的是,如果我把这5张桌子改成 -添加BIGINT标识代理主键(查询仍然使用GUID连接) -将先前的群集GUID主键降级为唯一列

然后它会在3:00分钟内运行

将它从BIGINT更改为INT可以得到大约1:30

群集GUID PK的运行速度如何可能明显快于自动递增的INT,并且远快于自动递增的BIGINT群集PK

注意:GUID值本身是在代码中生成的,而不是由DB生成的

看看这个简化的基准脚本,它演示了我的意思


使用您的测试用例,这是意料之中的。第一个测试只增长一个包含一个字段的表。另外两个构建两列和两个索引

这里有一个更合适的测试。这三个测试都有一个GUID字段和一个INT(或BIGINT)字段。所有字段都已编制索引。在我的服务器上,在UID上有非聚集索引的INT上有PK的测试表快了2秒


这是我的测试代码:

经过大量测试,使用guidpk比int代理键和guid自然键更快

关于避免由于集群和碎片而导致的GUID主键的讨论没有什么用处,因为如果您首先讨论的是GUID标识符,那么GUID很可能是数据模型固有的,无论如何都必须存储在数据模型中,因此单GUID主键显然是最简单、最快的选择(到目前为止)


简言之,如果你需要用guid识别记录,那么它们的键应该是guid!

你能提供一个简单的可运行脚本在你的机器上重现这些特征吗?@MartinSmith:是的,检查一下明显聚集的guid pk wins。啊,对。这并不奇怪。
int/bigint 案例而不仅仅是一个。非群集Guid的案例与群集Guid的案例具有完全相同的碎片问题。@MartinSmith:每个案例都有两个索引,速度仍然较慢。.同样在sql server 2008 enterprise上测试过,速度仍然较慢…哦,插入然后更新不到100000条记录不需要一分钟的时间。这很简单这是一个非常非常长的时间。表之间有外键引用也不会对性能产生影响。您应该用存储过程和表架构的内容来打开一个新的StackOverflow问题。这里有一些很奇怪的事情,您不应该这样做:
为了提高效率,我已经放弃了外键-表之间的键。
I还添加了
和(FILLFACTOR=90)
添加到GUID上的索引。这将有助于避免索引随着索引的增长而分裂。在添加了您指定的2个索引之后,在我的测试中,GUID聚集PK比INT IDENTITY更快3秒-。看来攻击GUID主键的人没有任何线索。哦,好吧,现在必须回滚一系列更改以使用直接GUID PK。如果删除事务处理,在测试之前创建表并执行,则在my server(SQL server 2008 R2 Enterprise、16 core等)上的情况正好相反事实上,这一点是很小的。事实上,集群的GUID键比集群身份+非集群GUID索引的性能要好或相称。您误解了集群GUID主键上索引碎片的问题。有2个问题:一个GUID是随机的,所以没有FILF f。actor,索引的B-树将不断分裂。这非常糟糕,但可以通过高填充因子在很大程度上克服。第二个问题是,表上的每个其他索引也必须保留指向PK的16字节,而不是4字节的INT数据类型。如果您所做的只是用GUI存储表,并且只测试插入速度,然后用fill对GUID进行PK。这篇博客文章为感兴趣的人提供了一个关于GUID上集群PKs的利弊分析:@tommy_o:不是我误解了你的观点,是SQL Server本身。我在2008/2012年进行了大量测试,发现FILLFACTOR的影响为0%。该博客建议将GUID设置为非集群密钥,但这意味着ns我需要一个额外的群集标识密钥,它可以将所有内容的速度降低2倍。如果您可以使用一些(可复制)验证您的声明,这可能会有所帮助证据。我浪费了2天的时间来调整数据库,只是为了恢复它。@ TMMYIO:我也用PADYORKINDEX改变了测试,有0%的影响。微软的博客做的解释很好。你的测试不够大,你的测试GUID需要在多个源上生成,以便它插入到B树的中间。