oracle - traductor - secuencia de oráculo de hibernación produce una gran brecha
traductor de frases en ingles a español gratis (8)
Como se dijo here , intente ajustar su SequenceGenerator.allocationSize
con su secuencia de la base de datos INCREMENT BY
number.
Estoy usando Hibernate 3, Oracle 10g. Tengo una mesa: sujeto. La definición está aquí
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 insertas un nuevo asunto, sub_seq se usa para crear un id. de sujeto, la definición está aquí
create sequence sub_seq
MINVALUE 1
MAXVALUE 999999999999999999999999999
START WITH 1
INCREMENT BY 1
CACHE 100
NOCYCLE ;
la clase Subject 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 scripts plsql de excel y la sub_secuencia funcionó bien. los números de sujeto van desde 1-4555.
sin embargo, cuando agregué un tema de mi aplicación usando hibernación, el número de secuencia saltó a 255050. Después de varios días de funcionamiento, los ID de sujeto generados por hibernación se ven así.
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 varias brechas grandes: 4555 a 255051, 255067 a 260051, 265057 a 270051
esto es un desperdicio y no un comportamiento deseado.
¿Alguien sabe por qué sucede esto y caliente para arreglarlo
Gracias
Creo que el problema proviene del hecho de que el generador de secuencia no es realmente un generador de secuencia, sino un generador de secuencia de secuencia, con un tamaño de asignación predeterminado de 50, como lo indica 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.
Verifica 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, ya que el valor generado crecería exponencialmente (tuvimos este problema y tuvimos identificaciones de entero negativas debido a desbordamiento)
De acuerdo con JB. Pero aún así, gracias a PaulJ.
Para ser más específico 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 usa javax.persistence.SequenceGenerator
, hibernate use hilo y posiblemente creará grandes lagunas en la secuencia. Hay una publicación que aborda este problema: https://forum.hibernate.org/viewtopic.php?t=973682
Hay dos formas de solucionar este problema
- En la anotación SequenceGenerator, agregue
allocationSize = 1, initialValue= 1
en lugar de usar javax.persistence.SequenceGenerator, use 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.
En realidad, tener allocationSize = 1 está bien si tu secuencia INCREMENT VALUE
es 1 y no tienes la necesidad de persistir en muchas entidades. Sin embargo, si desea conservar 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 debe buscar un ID, por lo tanto, se necesita una lectura de base de datos.
Para resolver este problema, debemos establecer el allocationSize
en algo así como 500 y secuenciar INCREMENT VALUE
en DB también a 500, luego lo más importante agregar una configuración hibernate.id.new_generator_mappings
para pedirle que use la nueva implementación del generador de secuencia, aquí supongamos que establece 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 forma, Hibernate usará SequenceStyleGenerator
lugar del antiguo SequenceHiLoGenerator
para generar los ids. 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.
Mira mi publicación para más detalles si estás en el mismo barco:
vcfvct.wordpress.com/2016/04/23/jpa-sequencegenerator-with-allocationsize-1-performance-tuning/
La respuesta más exitosa sería:
@Id
@SequenceGenerator (name = "id_sequence", sequenceName = "sq50")
@GeneratedValue(strategy = GenerationType.AUTO, generator = "id_sequence")
public int getId() {
return id;
}
Otra solución es:
Use ''strategy = GenerationType.AUTO'' en lugar de ''strategy = GenerationType.SEQUENCE'', como se muestra a continuación
@Id
@SequenceGenerator(name = "studentId", sequenceName = "student_Id")
@GeneratedValue(strategy = GenerationType.AUTO, generator="studentId")
private int studentId;
Si lee el siguiente enlace, verá que el problema está causado por la configuración de CACHE en su comando de creación de secuencia. La eliminación de la configuración de caché resolverá el problema hasta cierto punto, pero no tiene en cuenta la posibilidad de retrocesos, etc.
El enlace es: http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:369390500346406705
La única forma de volver a sincronizar sus secuencias ahora es volver a crear la secuencia, cambiar el nombre de la tabla actual y crear la tabla de nuevo y luego volver 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 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. Pablo
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.
Tuve este problema que tienen múltiples 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 la cuerda
<property name="hibernate.id.new_generator_mappings" value="false" />