什么是高/低算法?
我已经在NHibernate文档中找到了这一点(这是生成唯一密钥的一种方法,第5.1.4.2节),但是我没有找到有关其工作原理的很好的解释。
我知道Nhibernate可以处理它,并且我不需要了解内部,但是我很好奇。
什么是高/低算法?
我已经在NHibernate文档中找到了这一点(这是生成唯一密钥的一种方法,第5.1.4.2节),但是我没有找到有关其工作原理的很好的解释。
我知道Nhibernate可以处理它,并且我不需要了解内部,但是我很好奇。
Answers:
基本思想是,您有两个数字组成主键-“高”数字和“低”数字。客户端可以从本质上增加“高”序列,知道它随后可以安全地从先前的“高”值的整个范围(具有各种“低”值)生成密钥。
例如,假设您有一个“高”序列,当前值为35,而“低”数在0-1023范围内。然后客户端可以将序列增加到36(其他客户端在使用35时能够生成密钥),并知道密钥35 / 0、35 / 1、35 / 2、35 / 3 ... 35/1023是全部可用。
能够在客户端设置主键,而不是在没有主键的情况下插入值然后将其取回客户端的功能非常有用(尤其是在ORM中)。除了其他方面,这意味着您可以轻松建立父子关系,并在进行任何插入操作之前就将所有密钥都放置到位,这使批处理更为简单。
除了乔恩的答案:
用于断开连接。然后,客户端可以向服务器请求一个hi号,并创建增加lo号本身的对象。在lo范围用完之前,无需联系服务器。
高/低算法将序列域分为“高”组。同步分配一个“ hi”值。每个“ hi”组都有最大数量的“ lo”条目,可以通过离线分配它们,而不必担心并发重复的条目。
标识符范围由以下公式给出:
[(hi -1) * incrementSize) + 1, (hi * incrementSize) + 1)
而“ lo”值将在以下范围内:
[0, incrementSize)
从以下值开始应用:
[(hi -1) * incrementSize) + 1)
使用所有“ lo”值时,将获取新的“ hi”值,并且循环继续
您可以在本文中找到更详细的解释:
这个视觉演示也很容易遵循:
虽然hi / lo优化器可以优化标识符生成,但是在不了解标识符策略的情况下,它不能与其他将行插入数据库的系统配合使用。
Hibernate提供了pool-lo优化器,它提供了hi / lo生成器策略的优点,同时还提供了与其他不了解此序列分配策略的第三方客户端的互操作性。
与传统的高/低标识符策略相比,池低优化器既高效又可与其他系统互操作,是更好的选择。
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "name") @SequenceGenerator(name="name", sequenceName = "name_seq", allocationSize=100)
我的ID。
, (hi * incrementSize) + 1)
……应该是, hi * incrementSize)
吧?
Lo是一个缓存的分配器,通常根据某些机器字的大小,而不是人类可能会明智选择的有意义的大小范围(例如,一次获取200个密钥),将密钥空间分成大块。
高低使用往往会在服务器重新启动时浪费大量密钥,并会生成大量的人为不友好的密钥值。
比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%移植。分配性能等同于高低。
与Ambler的想法不同,它将键空间视为连续的线性数字线。
这样可以避免使用组合键(从来都不是一个好主意),并且可以避免在服务器重新启动时浪费整个lo-word。它生成“友好的”,人类规模的键值。
相比之下,Ambler先生的想法是分配高16位或32位,并随着高字数的增加而生成较大的对人不友好的键值。
分配的密钥比较:
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之类的持久性框架提供了更简单,更好的分配器作为其默认值。
根据我的经验,我发现Hi / Lo算法非常适合具有复制方案的多个数据库。想象一下。您在纽约有一个服务器(别名01),在洛杉矶有另一个服务器(别名02),那么您有一个PERSON表...因此在纽约,当创建一个人时,您始终将01用作HI值LO值是下一个安全对象。例子。
在洛杉矶,您始终使用HI02。例如:
因此,当您使用数据库复制(无论使用什么品牌)时,所有主键和数据都可以轻松自然地组合在一起,而不必担心重复的主键,冲突等。
在这种情况下,这是最好的方法。