NHibernate HiLo的说明

时间:2010-04-29 15:41:09

标签: .net nhibernate

我很难理解HiLo发生器在NHibernate中的工作原理。我已经阅读了here的解释,这使得事情变得更加清晰。

我的理解是每个SessionFactory都从数据库中检索高值。这样可以提高性能,因为我们可以在不访问数据库的情况下访问ID。

上述链接的解释也说明:

  

例如,假设您有一个当前值为35的“高”序列,而“低”号则在0-1023范围内。然后客户端可以将序列递增到36(对于其他客户端,当它使用35时能够生成密钥)并且知道密钥35 / 0,35 / 1,35 / 2,35 / 3 ... 35/1023是全部可用。

这是如何在Web应用程序中工作的,因为我只有一个SessionFactory,因此只有一个hi值。这是否意味着在断开连接的应用程序中,您最终可能会在实体表中出现重复(低)ID?

在我的测试中,我使用了以下设置:

<id name="Id" unsaved-value="0">
  <generator class="hilo"/>
</id>

我跑了一个测试来保存100个对象。我的表中的ID从32768 - 32868开始。下一个hi值增加到2.然后我再次运行我的测试,Ids在65536 - 65636范围内。

首先,为什么从32768而不是1开始,其次为什么从32868跳到65536?

现在我知道我的代理键不应该有任何意义,但我们在我们的应用程序中使用它们。为什么我不能让它们像SQL Server身份字段那样很好地增加。

最后有人可以解释一下max_lo参数的工作原理吗?这是可以根据高值创建的低值(我脑中的实体ID)的最大数量吗?

这是NHibernate中的一个主题,我一直在努力寻找文档。我在动作书中阅读了整个NHibernate,但它仍然没有详细介绍它的工作原理。

由于 本

4 个答案:

答案 0 :(得分:21)

我相信你的理解或多或少是正确的。 max_lo参数仅用于确定任何给定Hi值的可用ID数。

我最好的猜测是NHibernate的默认max_lo值是32768.因此,Hi值为1会在32768处启动你的ID并向右运行到65535. Hi值为2将从65536开始并运行另一个max_lo Ids

基本上,您使用max_lo值来控制Id碎片。对于每种情况,32768可能不是最佳值。

重要的是要注意,这只适用于SessionFactory的范围。如果你正在停止/启动你的应用程序并重新初始化SessionFactory,它会在启动时增加Hi值,你会看到你的Ids跳得很快。

答案 1 :(得分:9)

查看我的Nhibernate 3 HiLo对象生成的键,算法如下: (嗨* Lo)+嗨

所以我的Hivalue在数据库中为390,我的配置如下:

<id name="TimeclockId" column="TimeclockId" type="Int64" unsaved-value="0">
      <generator class="hilo">
        <param name="where">TableId = 1</param>
        <param name="table">HiValue</param>
        <param name="column">NextValue</param>
        <param name="max_lo">10</param>
      </generator>
    </id>

我重启我的应用程序池并得到(390 * 10)+ 390 = 4290,范围是4290 - 4300。

这就是为什么你的主键看起来很奇怪的原因,因为hi值391的下一个生成键是4301,范围是4301 - 4311。

答案 2 :(得分:2)

对于那些想知道如何选择良好max_lo值的人来说,权衡取决于:

  • 您需要从db中查询新hi值的频率。
  • 您实际可以生成的最大唯一数字数量。

较低的max_lo会确保没有&#34;浪费&#34; id's,它反过来控制你将达到数据类型的隐式限制的时刻(可能是int)。您支付的价格是每个客户需要更频繁地查询和增加hi值。

较高的max_lo有助于减少获取和增加hi的查询的频率,但会导致更多浪费。

确定最佳值时需要考虑的指标是:

  • 创建新实体并需要ID的频率
  • 应用程序重新启动/被回收的频率(导致新的NHibernate SessionFactory的任何内容)

让我们考虑一个在IIS中托管的Web应用程序,并且每24小时回收一次。实体为CustomerOrder

现在让我们假设:

  • 每24小时10000个新订单
  • 每24小时新增10位客户

然后,对于订单,完美max_lo10000,对于客户,10max_lo。当然,在现实世界中,你永远无法清楚地确定它,但你应该在这里得到这个想法!

现在让我们考虑一下我们选错了(荒谬)max_lo的不同情况:

  • 假设有10个客户每秒同时发出订单,订单中hi只有10个,每秒有一个多余的数据库调用来递增max_lo
  • 假设您的应用是桌面应用,并安装在50个客户端(支持人员?)上,每个客户端每天启动两次。他们一起每天创造约100张帮助台票。现在让我们说我们坚持使用Hi默认值32767. int每天增加100次(50个客户端* 2),这意味着您将达到{{1}的最大值少于2年,如果你忘记了hi如此频繁增加的重要事实。这里好max_lo(100票/ 50个客户)=仅2。

希望这有助于概念化HiLo算法及其在一般情况下的含义,同时也为您提供数字以实际在max_lo上添加数字。

答案 3 :(得分:1)

NHibernate 3.1.1使用HiLo

生成ID
if (lo > maxLo)
{
    long hival = <GetNextHiFromDB>
    lo = hival == 0 ? 1 : 0;
    hi = hival * (this.maxLo + 1L);
}
long result = hi + lo;
lo++;
return result;

在NHibernate配置中,您指定maxLo。如果maxLo设置为100,则每个hi值将获得101个ID。