2010-04-29 61 views
33

我很努力想知道HiLo生成器如何在NHibernate中工作。我读过解释here,这使得事情更清晰一些。NHibernate HiLo的解释

我的理解是每个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参数是如何工作的?这是低价值的最大数量(我头脑中的实体标识),可以根据高价值创建吗?

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

感谢 本

回答

21

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

我最好的猜测是NHibernate的默认max_lo值是32768.因此,Hi值为1将启动您的Id值32768并运行您直到65535. Hi值为2将从65536开始并运行另一个max_lo IDS。

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

但是需要注意的是,这只能在SessionFactory的范围内使用。如果你正在停止/启动应用程序并重新初始化SessionFactory,那么无论如何它会在启动时增加Hi值,并且你会看到你的Ids跳得很快。

+0

感谢您的解释。 – 2010-05-10 11:34:20

+3

默认的max_lo值是java short.MAX_VALUE == 2^15-1 = 32767 – kommradHomer 2012-03-08 15:19:43

9

看着我的NHibernate的3希洛对象生成的密钥,算法是这样的: (高*罗)+喜

我Hivalue在DB作为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

这就是为什么你在你的主键得到看似怪异的差距,因为接下来从391的hi值生成密钥是4301,范围为4301 - 4311

+0

这是一个不错而干净的解释。尽管他们实际上将公式形成为(max_lo + 1)* hi。我认为它更清洁,并指出你的id域被分成与max_lo + 1值一样大的块,而不是max_lo。 – kommradHomer 2012-03-08 13:42:45

1

NHibernate的3.1.1这样做是为了利用高住低训

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

NHibernate的内部配置指定器MAX10生成ID。如果maxLo设置为100,则每个hi值将得到101个ID。

1

对于那些想知道如何选择一个好的max_lo值,权衡本质之间:与您需要查询从一个数据库中的新hi

  • 频率。
  • 您实际上最大的唯一数字量可以生成。

较低max_lo将确保没有ID的的“浪费”,这反过来支配上,你会打你的数据类型的隐式极限(这将可能是int)的时刻。您支付的价格是每个客户需要更频繁地查询和增加价值。

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

你需要考虑,以确定最佳值的指标是:在这新的实体创建

  • 频率,需要一个ID
  • 频率在该应用程序重新启动/得到回收(什么导致新的NHibernate SessionFactory)

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

现在让我们假设:

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

再完美的max_lo10000的订单量和10供客户选择。当然,在现实世界中,你永远无法如此谨慎清楚地确定它,但你应该在这里得到这个想法!

现在让我们考虑不同的场景,我们选择完全错了(可笑)max_lo的:

  • 假设一个10名顾客同时作出命令每一秒,对订单的max_lo只有10,每一秒有一个多余的数据库调用来增加hi
  • 假设你的应用程序是一个桌面应用程序,并安装在50个客户端(支持人员?)上,每个客户端每天启动约两次。他们一起创建每天约100个帮助台门票。现在我们假设我们坚持max_lo默认为32767. Hi每天增加100次(50个客户端* 2),这意味着您将在的最大值int以内不到2年,如果您忘记了重要的事实上,hi得到增加如此频繁。这里良好的max_lo会(门票100元/ 50客户端)=仅2

希望这有助于概念化希洛算法及其在一般的意义,同时也给你的数学实际贴在max_lo一些。