首页 文章

什么是Hi / Lo算法?

提问于
浏览
433

什么是Hi / Lo算法?

我在NHibernate文档中找到了这个(它's one method to generate unique keys, section 5.1.4.2), but I haven' t找到了它如何工作的一个很好的解释 .

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

5 回答

  • 20

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

    • “hi”令牌由数据库分配,并且两个并发调用保证看到唯一的连续值

    • 一旦检索到“hi”标记,我们只需要“incrementSize”(“lo”条目的数量)

    • 标识符范围由以下公式给出:

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

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

    [0, incrementSize)
    

    从起始值应用:

    [(hi -1) * incrementSize) + 1)
    
    • 当使用所有“lo”值时,将获取新的“hi”值并继续循环

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

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

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

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

  • 495

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

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

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

  • 144

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

    • 010000010杰森

    • 010000011大卫

    • 010000012 Theo

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

    • 020000045鲁珀特

    • 020000046奥斯瓦尔德

    • 020000047马里奥

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

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

  • 1

    除了Jon的回答:

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

  • 21

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

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

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

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

    如果您可以提交此事务(使用重试来处理争用),您已经分配了20个密钥并可以根据需要进行分配 .

    该方案的块大小仅为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
    

    我实际上是在90年代与Ambler先生通信,向他提出了这个改进方案,但他太过坚持并且顽固地承认使用线性的优点和简单明了号线 .

    在设计方面,他的解决方案在数字线(复合键,大型hi_word产品)上基本上比Linear_Chunk更复杂,同时没有实现相对的好处 . 因此,他的设计在数学上被证明是有缺陷的 .

相关问题