我正在使用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。
答案 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关键字。当然,正如之前的评论中所解释的那样,这将限制序列吞吐量并可能妨碍您的应用程序性能。