Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

hibernate oracle sequence produces large gap

I am using hibernate 3 , oracle 10g. I have a table: subject. The definition is here

CREATE TABLE SUBJECT     (       SUBJECT_ID NUMBER (10),       FNAME VARCHAR2(30)  not null,       LNAME VARCHAR2(30)  not null,       EMAILADR VARCHAR2 (40),      BIRTHDT  DATE       not null,      constraint pk_sub primary key(subject_id) USING INDEX TABLESPACE data_index     )  ; 

when insert a new subject, sub_seq is used to create an subject id, the definition is here

create sequence sub_seq        MINVALUE 1         MAXVALUE 999999999999999999999999999         START WITH 1        INCREMENT BY 1         CACHE 100         NOCYCLE ; 

the Subject class is like this:

@Entity @Table(name="ktbs.syn_subject") public class Subject {      @Id      @Column(name="subject_id")     @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SUB_SEQ")     @SequenceGenerator(name="SUB_SEQ", sequenceName = "SUB_SEQ")     private long subjectId;     private String fname;     private String lname;     private String emailadr;     private Date birthdt; } 

in the subject table , there have been 4555 subjects in the database loaded by plsql scripts from excel and the sub_sequence worked fine. subject ids range from 1--4555.

however, when i added a subject from my application using hibernate, the sequence number jumped to 255050. After several days running, the subject ids generated by hibernate look like this

270079 270078 270077 270076 270075 270074 270073 270072 270071 270070 270069 270068 270067 270066 270065 270064 270063 270062 270061 270060 270059 270058 270057 270056 270055 270054 270053 270052 270051 270050 265057 265056 265055 265054 265053 265052 265051 265050 260059 260058 260057 260056 260055 260054 260053 260052 260051 260050 255067 255066 255065 255064 255063 255062 255061 255060 255059 255058 255057 255056 255055 255054 255053 255052 255051 255050 4555 4554 4553 . . . . 1 

There are several large gaps: 4555 to 255051, 255067 to 260051, 265057 to 270051

this is a waste and not a desired behavior.

does anyone know why this happens and hot to fix it

Thanks

like image 357
sse Avatar asked Mar 17 '11 22:03

sse


People also ask

What is the difference between cache and Nocache in sequence?

Oracle recommends using the CACHE setting to enhance performance if you are using sequences in a Real Application Clusters environment. Specify NOCACHE to indicate that values of the sequence are not preallocated. If you omit both CACHE and NOCACHE , the database caches 20 sequence numbers by default.

What is allocationSize in hibernate sequence?

allocationSize - (Optional) The amount to increment by when allocating sequence numbers from the sequence.

How does hibernate sequence generator work?

SEQUENCE Generation. To use a sequence-based id, Hibernate provides the SequenceStyleGenerator class. This generator uses sequences if our database supports them. It switches to table generation if they aren't supported.


2 Answers

I think that the problem comes from the fact that the sequence generator is not really a sequence generator, but a sequence hilo generator, with a default allocation size of 50. as indicated by the documentation : http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping-identifier

This means that if the sequence value is 5000, the next generated value will be 5000 * 50 = 250000. Add the cache value of the sequence to the equation, and it might explain your huge initial gap.

Check the value of the sequence. It should be less than the last generated identifier. Be careful not to reinitialize the sequence to this last generated value + 1, because the generated valus would grow exponentially (we've had this problem, and had negative integer ids due to overflow)

like image 187
JB Nizet Avatar answered Nov 11 '22 07:11

JB Nizet


Agree with JB. But still thanks to PaulJ.

To be more specific to my annotation code below:

@Entity @Table(name="ktbs.syn_subject") public class Subject {    @Id    @Column(name="subject_id")   @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SUB_SEQ")   @javax.persistence.SequenceGenerator(name="SUB_SEQ", sequenceName = "SUB_SEQ")   private long subjectId;   private String fname;   private String lname;   private String emailadr;   private Date birthdt; } 

If you use javax.persistence.SequenceGenerator, hibernate use hilo and will possibly create large gaps in the sequence. There is a post addressing this problem: https://forum.hibernate.org/viewtopic.php?t=973682

There are two ways to fix this problem

  1. In the SequenceGenerator annotation, add allocationSize = 1, initialValue= 1
  2. instead of using javax.persistence.SequenceGenerator, use org.hibernate.annotations, like this:

    @javax.persistence.SequenceGenerator(     name = "Question_id_sequence",      sequenceName = "S_QUESTION" )  @org.hibernate.annotations.GenericGenerator(     name="Question_id_sequence",      strategy = "sequence",      parameters = {          @Parameter(name="sequence", value="S_QUESTION")      } ) 

I have tested both ways, which works just fine.

like image 25
sse Avatar answered Nov 11 '22 08:11

sse