我很难理解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,但它仍然没有详细介绍它的工作原理。
由于 本
答案 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
值的人来说,权衡取决于:
hi
值的频率。较低的max_lo
会确保没有&#34;浪费&#34; id's,它反过来控制你将达到数据类型的隐式限制的时刻(可能是int
)。您支付的价格是每个客户需要更频繁地查询和增加hi
值。
较高的max_lo
有助于减少获取和增加hi
的查询的频率,但会导致更多浪费。
确定最佳值时需要考虑的指标是:
让我们考虑一个在IIS中托管的Web应用程序,并且每24小时回收一次。实体为Customer
和Order
。
现在让我们假设:
然后,对于订单,完美max_lo
为10000
,对于客户,10
为max_lo
。当然,在现实世界中,你永远无法清楚地确定它,但你应该在这里得到这个想法!
现在让我们考虑一下我们选错了(荒谬)max_lo
的不同情况:
hi
只有10个,每秒有一个多余的数据库调用来递增max_lo
。 Hi
默认值32767. int
每天增加100次(50个客户端* 2),这意味着您将达到{{1}的最大值少于2年,如果你忘记了hi
如此频繁增加的重要事实。这里好max_lo
(100票/ 50个客户)=仅2。希望这有助于概念化HiLo算法及其在一般情况下的含义,同时也为您提供数字以实际在max_lo
上添加数字。
答案 3 :(得分:1)
NHibernate 3.1.1使用HiLo
生成IDif (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。