什么是Hi / Lo算法?

时间:2008-11-11 20:53:01

标签: database algorithm nhibernate hibernate hilo

什么是Hi / Lo算法?

我在NHibernate文档中找到了这个(这是生成唯一键的一种方法,第5.1.4.2节),但我没有找到它如何工作的很好的解释。

我知道Nhibernate处理它,我不需要知道内部,但我只是好奇。

5 个答案:

答案 0 :(得分:507)

基本思想是你有两个数字来组成一个主键 - 一个“高”数字和一个“低”数字。客户端基本上可以增加“高”序列,因为它知道它可以安全地从前一个“高”值的整个范围生成密钥,具有各种“低”值。

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

能够在客户端设置主键非常有用(特别是使用ORM),而不是在没有主键的情况下插入值,然后将它们提取回客户端。除了其他任何东西,它意味着您可以轻松地建立父/子关系,并在执行任何插入之前将所有键都放在适当的位置,这样可以简化它们的批处理。

答案 1 :(得分:147)

除了Jon的回答:

它用于能够断开连接。然后,客户端可以向服务器请求hi数字并创建增加lo数量的对象。在lo范围用完之前,它不需要联系服务器。

答案 2 :(得分:24)

hi / lo算法将序列域分成“hi”组。同步分配“hi”值。每个“hi”组都被赋予最大数量的“lo”条目,可以通过离线分配而不必担心并发重复条目。

  1. “hi”令牌由数据库分配,两个并发调用保证看到唯一的连续值
  2. 一旦检索到“hi”标记,我们只需要“incrementSize”(“lo”条目的数量)
  3. 标识符范围由以下公式给出:

    [(hi -1) * incrementSize) + 1, (hi * incrementSize) + 1)
    

    和“lo”值将在以下范围内:

    [0, incrementSize)
    

    从起始值:

    开始应用
    [(hi -1) * incrementSize) + 1)
    
  4. 当使用所有“lo”值时,将获取一个新的“hi”值并继续循环

  5. 您可以在this article中找到更详细的说明:

    这种视觉呈现也很容易理解:

    enter image description here

    虽然hi / lo优化器适用于优化标识符生成,但它不能很好地与其他系统在我们的数据库中插入行,而不了解我们的标识符策略。

    Hibernate提供pooled-lo优化器,它将hi / lo生成器策略与互操作性序列分配机制相结合。该优化器既高效又可与其他系统互操作,是比以前的传统hi / lo标识符策略更好的候选者。

答案 3 :(得分:20)

Lo是一个缓存的分配器,它将键空间分成大块,通常基于某些机器字大小,而不是人类可能合理选择的有意义大小的范围(例如,一次获得200个键)。

Hi-Lo的使用往往会在服务器重启时浪费大量的密钥,并产生大量的人类不友好的密钥值。

比Hi-Lo分配器更好,是“线性块”分配器。这使用了类似的基于表格的原则,但是分配了小的,方便大小的块和&产生良好的人性化价值观。

create table KEY_ALLOC (
    SEQ varchar(32) not null,
    NEXT bigint not null,
    primary key (SEQ)
);

分配下一个,比方说200个密钥(然后在服务器中保存为一个范围并根据需要使用):

select NEXT from KEY_ALLOC where SEQ=?;
update KEY_ALLOC set NEXT=(old value+200) where SEQ=? and NEXT=(old value);

假设您可以提交此事务(使用重试来处理争用),您已经分配了200个密钥&可以根据需要分发它们。

如果块大小只有20,这个方案比从Oracle序列分配快10倍,并且在所有数据库中都是100%可移植的。分配性能相当于hi-lo。

与Ambler的想法不同,它将键空间视为连续的线性数字线。

这避免了复合键的推动(这从来就不是一个好主意),并避免在服务器重启时浪费整个lo-words。它生成“友好”的人类关键值。

相比之下,Ambler先生的想法是分配高16位或32位,并在hi-words增量时产生大的人类不友好的键值。

分配密钥的比较:

Linear_Chunk       Hi_Lo
100                65536
101                65537
102                65538
.. server restart
120                131072
121                131073
122                131073
.. server restart
140                196608

在设计方面,他的解决方案在数字线(复合键,大型hi_word产品)上基本上比Linear_Chunk更复杂,同时没有实现相对的好处。

Hi-Lo设计在OO映射和持久性早期出现。目前,Hibernate等持久性框架提供了更简单,更好的分配器作为默认设置。

答案 4 :(得分:1)

根据我的经验,我发现Hi / Lo算法非常适合具有复制方案的多个数据库。想象一下。你有一个服务器在纽约(别名01)和另一台服务器在洛杉矶(别名02)然后你有一个PERSON表...... 所以在纽约,当一个人被创造时...你总是使用01作为HI值而LO值是下一个secuential。例子。

  • 010000010 Jason
  • 010000011大卫
  • 010000012 Theo

在洛杉矶你总是使用HI 02.例如:

  • 020000045鲁珀特
  • 020000046 Oswald
  • 020000047 Mario

因此,当您使用数据库复制(无论什么品牌)时,所有主键和数据都可以轻松自然地组合,而无需担心重复的主键,冲突等。

这是此方案中的最佳方式。