Hibernate序列生成器非连续值

时间:2010-09-02 06:22:41

标签: java oracle hibernate

我正在使用hibernate sequencegenerator为我的主键列自动生成唯一值。示例代码如下所示。

@Entity
@Table(name = "REQUEST")
@javax.persistence.SequenceGenerator(name = "REQ_SEQ", sequenceName = "REQUEST_SEQ")
public class Request {
/**
 * Unique id for this request
 */
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "REQ_SEQ")
@Column(name = "REQ_ID")
private long requestId;
   //So on
}

除了生成的值是交错的这一事实外,一切正常。例如,它插入值为5000到5015(15个插入),然后第16个插入产生的值为5100.然后它适用于一些后续插入并再次出现问题。 我没有任何问题,只要生成的值是唯一的,但只是好奇知道是什么原因造成的。仅供参考,我使用的是Oracle。

2 个答案:

答案 0 :(得分:9)

Oracle序列以这种方式工作。它们只保证唯一性,但它们不保证连续值,因为它会妨碍并行性。

他们在内部做的或多或少是这样的:当您请求序列中的下一个值时,Oracle预先计算一大块值(在您的情况下为5000-5099)并将其放入序列缓存中,然后设置seq。 nextval =磁盘上的5100。但是,如果由于活动,db必须从缓存中丢弃你的一大块值,那么当下次访问seq.nextval时,它将需要另一个块5100-5199。也就是说,Oracle甚至不会尝试保存已放入缓存的序列值。

关键在于序列缓存是一种内存结构,它比序列本身更快,更可并行化,这是一种磁盘上的结构。由于我们希望扩展,我们希望避免尽可能多地访问磁盘。

您可以使用序列DDL中的CACHE子句控制给定序列的块大小:

CREATE SEQUENCE seq2
CACHE 50;

答案 1 :(得分:0)

来自Oracle doc:

CREATE SEQUENCE customers_seq
  START WITH    1000
  INCREMENT BY  1
  NOCACHE;

如果您想要一系列ID,可以使用NOCACHE关键字。当然,正如之前的评论中所解释的那样,这将限制序列吞吐量并可能妨碍您的应用程序性能。