2011-03-17 22 views
29

Estoy usando hibernate 3, oráculo 10g. Tengo una mesa: sujeto. La definición está aquísecuencia de oráculo de hibernación produce una gran brecha

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 
    ) 
; 

cuando se inserte un nuevo sujeto, sub_seq se utiliza para crear un identificador de objeto, la definición es aquí

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

la clase sujeto es así:

@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; 
} 

en la tabla de materias, ha habido 4555 sujetos en la base de datos cargados por las secuencias de comandos plsql de excel y la sub_secuencia funcionó bien. los números de sujeto van desde 1-4555. Sin embargo

, cuando he añadido un tema de mi solicitud para el uso de hibernación, el número de secuencia saltó a 255050. Después de varios días seguidos, los identificadores de sujetos generados por la mirada de hibernación como esto

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 

Hay varios grandes huecos: 4555 a 255051, 255067 a 260051, 265057 a 270051

esto es un desperdicio y no es un comportamiento deseado.

¿alguien sabe por qué sucede esto y caliente para fijarlo

Gracias

Respuesta

36

Creo que el problema viene del hecho de que el generador de secuencia no es realmente un generador de secuencias, sino un generador de secuencias de hilo, con un tamaño de asignación por defecto de 50 como se indica en la documentación: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping-identifier

Esto significa que si el valor de secuencia es 5000, el siguiente valor generado será 5000 * 50 = 250000. Agregue el valor de caché de la secuencia a la ecuación, y podría explicar su gran brecha inicial.

Compruebe el valor de la secuencia. Debe ser menor que el último identificador generado.Tenga cuidado de no reinicializar la secuencia a este último valor generado + 1, porque el valus generado crecería exponencialmente (tuvimos este problema y tuvimos identificadores enteros negativos debido al desbordamiento)

+0

gracias. sí, ese puede ser el problema. así que hibernate aquí en mi caso ¿no usa la dosis el objeto de secuencia definido por Oracle? ¿Cómo arreglar este problema? – sse

+0

también obtienes huecos de reinicios si recuerdo cuando la configuración es correcta, ya que la secuencia en la base de datos es 1, 2, 3, 4, y si el tamaño de asignación es 500, luego cuando se vuelve a colocar, 500 * 1 = 500 y cuando finalmente llega a 999, llama a obtener la secuencia siguiente recuperando 2 (o 3 si otro proceso obtuvo 2 ya), y luego 500 * 2 = 1000 hasta 1499. El servidor se reinicia después de usar solo 1 o 2 valores en el 500 un hueco. –

+0

oh, y cuando llamas persiste y no enjuagas (si está en modo manual) usa los identificadores de la secuencia que nunca se guardan en la base de datos (hay muchos motivos, como acabo de notar, no estás usando allocationSize que utilizamos ALOT para evitar la interacción de db constante en operaciones de inserción, ya que es más trabajo de ida y vuelta) –

5

Si se lee el siguiente enlace, verá que el problema es causado por la configuración de caché en su comando de creación de secuencia. Extracción de la configuración de caché va a resolver el problema en un grado - pero no tener en cuenta la posibilidad de reversiones, etc.

Link es: http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:369390500346406705

La única manera de sincronizar sus secuencias ahora es volver a crear la secuencia, cambie el nombre de la tabla actual y cree la tabla nuevamente y luego vuelva a insertar los registros de la tabla anterior en la nueva tabla.

NOTA: El valor de caché para secuencias es útil para cargas grandes donde los valores de secuencia 'x' se asignan a la vez. Si está utilizando un sistema de transacciones en el que realiza una inserción a la vez, entonces el almacenamiento en caché no es útil (o debo decir, nunca lo he encontrado útil).

NOTA: Esta es mi comprensión de la opción de caché para las secuencias. Puede buscar Oracle Documentation en los comandos CREATE SEQUENCE para obtener más información. Pero el enlace de arriba debe proporcionar una respuesta razonable a su pregunta.

Gracias. Paul

+0

gracias. pero la brecha es de 10000 y la brecha definida es 100. ¿Está relacionada con la configuración de hibernación? – sse

+2

Cada vez que hace una inserción, asigna 100 valores de secuencia. Entonces, una brecha de 10,000 solo está insertando 1,000 o 100 registros. Necesitará leer los cachés de secuencias para obtener más detalles, pero el punto principal es que no puede confiar en una secuencia para mantener un conjunto secuencial de valores, ya que los espacios SIEMPRE estarán presentes independientemente del valor de caché. – PaulJ

+1

Acabo de emitir la consulta del desarrollador sql seleccione sub_seq.nextval desde dual; muestra 5408. lo que significa que la dosis de hibernación no usa el objeto de secuencia de oráculo sub_seq. sospecho que hay algo mal con la configuración de hibernación – sse

35

De acuerdo con JB. Pero aún así, gracias a PaulJ.

Para ser más específicos a mi código de anotación a continuación:

@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; 
} 

Si utiliza javax.persistence.SequenceGenerator, Hibernate uso Hilo y posiblemente crear grandes huecos en la secuencia. Hay un puesto de abordar este problema: https://forum.hibernate.org/viewtopic.php?t=973682

Hay dos maneras de solucionar este problema

  1. En la anotación SequenceGenerator, añadir allocationSize = 1, initialValue= 1
  2. en lugar de utilizar javax.persistence.SequenceGenerator, utilice org .hibernate.annotations, así:

    @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") 
        } 
    ) 
    

He probado ambas formas, lo cual funciona bien.

+1

Gracias !!!!!!!!!! – Nick

+0

¡Sí funcionó! – Ajit

6

Otra solución es:

Uso estrategia = GenerationType.AUTO 'en lugar de 'estrategia = GenerationType.SEQUENCE', como a continuación

@Id 
@SequenceGenerator(name = "studentId", sequenceName = "student_Id") 
@GeneratedValue(strategy = GenerationType.AUTO, generator="studentId") 
private int studentId; 
+0

Gracias esto funcionó en mi caso –

1

La respuesta más acertado sería:

@Id 
@SequenceGenerator (name = "id_sequence", sequenceName = "sq50") 
@GeneratedValue(strategy = GenerationType.AUTO, generator = "id_sequence") 
public int getId() { 
return id; 
} 
0

Como dijo here, intente ajustar su SequenceGenerator.allocationSize con su secuencia de base de datos número INCREMENT BY.

6

Actualmente, allocationSize = 1 está bien si su secuencia INCREMENT VALUE es 1 y no necesita persistir una gran cantidad de entidades. Sin embargo, si desea persistir miles o millones de registros, la configuración anterior podría convertirse en un cuello de botella de rendimiento ya que cada vez que se guarde necesitará obtener una identificación, por lo tanto, necesitará una lectura de db.

Para resolver este problema, es necesario establecer el allocationSize a algo así como 500 y la secuencia INCREMENT VALUE en el PP también a 500, lo más importante añadir un hibernación establecer hibernate.id.new_generator_mappings para pedirle que utilice la nueva aplicación generador de secuencias, aquí asumo establecer sus propiedades de hibernación en una clase de configuración de java:

properties.setProperty("hibernate.id.new_generator_mappings", Boolean.toString(true)); 

de esta manera, Hibernate usará SequenceStyleGenerator en lugar de la antigua SequenceHiLoGenerator para generar los identificadores. El SequenceStyleGenerator es más amigable para jpa y oracle. Genera valores de identificador basados ​​en una estructura de base de datos de estilo de secuencia. Las variaciones van desde usar una secuencia hasta usar una tabla para imitar una secuencia.

mirada a mi post para más detalles si están en el mismo barco:

vcfvct.wordpress.com/2016/04/23/jpa-sequencegenerator-with-allocationsize-1-performance-tuning/

1

Tuve problemas similares. generador de secuencia y generador de secuencia de secuencia son bastante similares pero tienen diferencias. En hibernate 3, el generador de hilo se multiplica por el valor predeterminado 50. Por lo tanto, no es necesario incrementar la secuencia DB. Por otro lado, las versiones posteriores de hibernate usan un generador de secuencia por defecto. Por lo tanto, se requiere un incremento de DB de 50.

https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.3/html/Migration_Guide/Preserve_the_Existing_Behavior_of_the_Hibernate_Identity_Auto_Generated_Value1.html

Tenía este problema que tienen varias versiones de hibernación (3 y 5). La misma configuración funcionó bien (incrementó en 1 en DB). Pero falló en Hibernate 5. Por lo tanto, actualizo mi persistence.xml como se muestra a continuación. Esto asegura la generación de hilo

 <property name="hibernate.id.new_generator_mappings" value="false" /> 
Cuestiones relacionadas