无法解释使用Guid与Native Keys的Nhibernate的性能

时间:2012-01-19 13:13:17

标签: sql-server performance nhibernate guid increment

我们最近有关于已分配的GUID与自动增量主键的传统和正在进行的(根据SO搜索)论点。我们正在使用MSSQL 2008R2,NHibernate 2.05和.NET 4.0。

我做了大量的谷歌搜索和阅读关于使用两种不同密钥类型之间的相对插入性能差异的其他帖子。大多数博客文章似乎都是针对相当旧版本的MSSQL服务器,所以我想我会尝试对一些插页进行基准测试,看看它们是否符合人们的意思。

我编写了一个简单的应用程序,它只是将每个会话一行的200万个对象插入到数据库中,并且应用程序的两次运行之间的唯一区别是密钥类型。这两个键都是聚集的 - 所以根据我的阅读,这提供了一个很好的自动增量案例和Guid的最坏情况。

当看到结果时,我有点震惊......

由于没有进行正确的统计分析,我不想让Zed Shaw恐怖统治下来,我将数据加载到R中并生成一个情节(见下文)并得到以下汇总统计数据:

GUID键:

最低:0.00

第一四分位数:0.00

中位数:0.00

平均值:1.975

标准差:13.577490

第三个四分位数:1.0

最大:3824.0

原生(自动增量整数)键

最低:0.00

第一四分位数:0.00

中位数:0.00

平均值:1.644

标准差:12.491320

第三四分位数:0.00

最大:1932.00

假设表的大小和插入行所花费的时间之间应该存在线性关系,我尝试计算最小二乘回归,使用表大小作为预测器并获得以下结果:

GUID :0.002594

原生:0.002594

r平方值对我来说是最受关注的,根据我对统计数据的理解(无可否认有限)表格的大小与任何一种情况下的插入速度之间没有相关性。

我担心的是,我得到的结果并不符合普遍接受的智慧,我想知道SO-land中的任何人是否可以帮助我解释结果。我可以看到一些可能性:

  1. GUID的性能问题是以前版本的MSSQL服务器的问题,但不再是问题。
  2. 我写了一个糟糕的实验,我得到的结果毫无用处。
  3. 在查看数据库性能时我们之间的差异为0.331毫秒,我并没有合理地考虑这个值。
  4. 使用自动增量Id键时,往返数据库以获取Id确实会对性能产生影响。
  5. 使用四核计算机进行本地测试意味着有足够的备用CPU来处理后台线程中的索引。
  6. 我见过的所有统计数据都是针对使用生成的GUID的原始SQL而我正在测试的场景(使用NHibernate)是一个不同的情况。
  7. 我提前道歉,我不是一个数据库专家,所以我很难解释这些结果。

    干杯,

    Aidos

    plot

1 个答案:

答案 0 :(得分:1)

答案是#2,你写的一个经验并没有正确地反映出“公认的智慧”中的条件。三个问题:

首先,您要插入“每个会话一行”。这不是“公认的智慧”所关注的情况。以猫,小猫和伴侣的文档为例,其中猫有一只配偶和许多小猫。一次新建和插入整个猫科动物就是所讨论的情况,而不是一次一行。每行事务的开销会给您的测试带来很多噪音。

其次,“假设表格的大小和插入行所花费的时间之间应该存在线性关系”也是错误的。用于保存表的BTree结构具有大约O(log n)的一般情况插入时间。

第三,你看到guids vs identity的'慢'插入的原因与BTree的细节有关。插入到树的中间的速度较慢,因为可能会移动更多的数据,并且页面拆分的可能性要小得多。创建了guid-comb算法和生成器来缓解这个问题。 Guid-comb确保将来创建的guid总是比过去创建的guid更大,因此强制插入在表的末尾发生,这样更有效。 sql server中的newsequentialid函数使用了类似的策略。

要查看预测的性能,请使用identity,guid和guid-comb在父子关系中为每个事务插入数百行。