resueltos pedido modelos modelo inventarios eoq ejercicios ejemplos economica deterministicos deterministica demanda cantidad java hibernate jdbc

java - pedido - modelos de inventarios deterministicos pdf



Hibernate confusión de tamaño de lote (3)

Este programa hace decenas de miles de insertos consecutivos uno tras otro. Nunca he usado Hibernate antes. Estoy obteniendo un rendimiento extremadamente lento (si solo conecto y ejecuto el SQL manualmente, soy 10-12x más rápido. Mi batch_size está configurado en 50 según muchos tutoriales de hibernación.

Aquí hay un registro de un solo inserto, tal vez podrías ayudarme a entender exactamente lo que está sucediendo:

START INSERT 11:02:56.121 [main] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13106053761 11:02:56.121 [main] DEBUG o.h.transaction.JDBCTransaction - begin 11:02:56.121 [main] DEBUG org.hibernate.jdbc.ConnectionManager - opening JDBC connection 11:02:56.121 [main] TRACE o.h.c.DriverManagerConnectionProvider - total checked-out connections: 0 11:02:56.121 [main] TRACE o.h.c.DriverManagerConnectionProvider - using pooled JDBC connection, pool size: 0 11:02:56.121 [main] DEBUG o.h.transaction.JDBCTransaction - current autocommit status: false 11:02:56.121 [main] TRACE org.hibernate.jdbc.JDBCContext - after transaction begin 11:02:56.121 [main] TRACE org.hibernate.impl.SessionImpl - setting flush mode to: MANUAL 11:02:56.121 [main] TRACE o.h.e.def.DefaultLoadEventListener - loading entity: [com.xyzcompany.foo.edoi.ejb.msw000.MSW000Rec#component[keyW000]{keyW000=F000 ADSUFC}] 11:02:56.121 [main] TRACE o.h.e.def.DefaultLoadEventListener - creating new proxy for entity 11:02:56.122 [main] TRACE o.h.e.d.DefaultSaveOrUpdateEventListener - saving transient instance 11:02:56.122 [main] DEBUG o.h.e.def.AbstractSaveEventListener - generated identifier: component[keyW000]{keyW000=F000 ADSUFC}, using strategy: org.hibernate.id.CompositeNestedGeneratedValueGenerator 11:02:56.122 [main] TRACE o.h.e.def.AbstractSaveEventListener - saving [com.xyzcompany.foo.edoi.ejb.msw000.MSW000Rec#component[keyW000]{keyW000=F000 ADSUFC}] 11:02:56.123 [main] TRACE o.h.e.d.AbstractFlushingEventListener - flushing session 11:02:56.123 [main] DEBUG o.h.e.d.AbstractFlushingEventListener - processing flush-time cascades 11:02:56.123 [main] DEBUG o.h.e.d.AbstractFlushingEventListener - dirty checking collections 11:02:56.123 [main] TRACE o.h.e.d.AbstractFlushingEventListener - Flushing entities and processing referenced collections 11:02:56.125 [main] TRACE o.h.e.d.AbstractFlushingEventListener - Processing unreferenced collections 11:02:56.125 [main] TRACE o.h.e.d.AbstractFlushingEventListener - Scheduling collection removes/(re)creates/updates 11:02:56.126 [main] DEBUG o.h.e.d.AbstractFlushingEventListener - Flushed: 1 insertions, 0 updates, 0 deletions to 62 objects 11:02:56.126 [main] DEBUG o.h.e.d.AbstractFlushingEventListener - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections 11:02:56.132 [main] TRACE o.h.e.d.AbstractFlushingEventListener - executing flush 11:02:56.132 [main] TRACE org.hibernate.jdbc.ConnectionManager - registering flush begin 11:02:56.132 [main] TRACE o.h.p.entity.AbstractEntityPersister - Inserting entity: [com.xyzcompany.foo.edoi.ejb.msw000.MSW000Rec#component[keyW000]{keyW000=F000 ADSUFC}] 11:02:56.132 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0) 11:02:56.132 [main] DEBUG org.hibernate.SQL - insert into MSW000 (W000_DATA_REC, W000_FILE_FLAGS, KEY_W000) values (?, ?, ?) 11:02:56.132 [main] TRACE org.hibernate.jdbc.AbstractBatcher - preparing statement 11:02:56.132 [main] TRACE o.h.p.entity.AbstractEntityPersister - Dehydrating entity: [com.xyzcompany.foo.edoi.ejb.msw000.MSW000Rec#component[keyW000]{keyW000=F000 ADSUFC}] 11:02:56.132 [main] TRACE org.hibernate.type.StringType - binding '' ADSUFCA '' to parameter: 1 11:02:56.132 [main] TRACE org.hibernate.type.StringType - binding '' '' to parameter: 2 11:02:56.132 [main] TRACE org.hibernate.type.StringType - binding ''F000 ADSUFC'' to parameter: 3 11:02:56.132 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - Executing batch size: 1 11:02:56.133 [main] DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1) 11:02:56.133 [main] TRACE org.hibernate.jdbc.AbstractBatcher - closing statement 11:02:56.133 [main] TRACE org.hibernate.jdbc.ConnectionManager - registering flush end 11:02:56.133 [main] TRACE o.h.e.d.AbstractFlushingEventListener - post flush 11:02:56.133 [main] DEBUG o.h.transaction.JDBCTransaction - commit 11:02:56.133 [main] TRACE org.hibernate.impl.SessionImpl - automatically flushing session 11:02:56.133 [main] TRACE org.hibernate.jdbc.JDBCContext - before transaction completion 11:02:56.133 [main] TRACE org.hibernate.impl.SessionImpl - before transaction completion 11:02:56.133 [main] DEBUG o.h.transaction.JDBCTransaction - committed JDBC Connection 11:02:56.133 [main] TRACE org.hibernate.jdbc.JDBCContext - after transaction completion 11:02:56.133 [main] DEBUG org.hibernate.jdbc.ConnectionManager - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! 11:02:56.133 [main] TRACE org.hibernate.impl.SessionImpl - after transaction completion 11:02:56.133 [main] TRACE org.hibernate.impl.SessionImpl - closing session 11:02:56.133 [main] TRACE org.hibernate.jdbc.ConnectionManager - performing cleanup 11:02:56.133 [main] DEBUG org.hibernate.jdbc.ConnectionManager - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] 11:02:56.133 [main] TRACE o.h.c.DriverManagerConnectionProvider - returning connection to pool, pool size: 1 11:02:56.133 [main] TRACE org.hibernate.jdbc.JDBCContext - after transaction completion 11:02:56.133 [main] DEBUG org.hibernate.jdbc.ConnectionManager - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! 11:02:56.134 [main] TRACE org.hibernate.impl.SessionImpl - after transaction completion FINISH INSERT


Cuando llame a session.save() , hibernate generará un INSERT SQL. Este INSERTAR SQL se adjuntará para emitirse a la base de datos durante la descarga (es decir, session.flush() ).

Durante la descarga, si hibernate.jdbc.batch_size se establece en algún valor distinto de cero, Hibernate utilizará la función de procesamiento por lotes introducida en la API JDBC2 para emitir el SQL de inserción por lotes al DB.

Por ejemplo, si save() 100 registros y su hibernate.jdbc.batch_size se establece en 50. Durante la descarga, en lugar de emitir el siguiente SQL 100 veces:

insert into TableA (id , fields) values (1, ''val1''); insert into TableA (id , fields) values (2, ''val2''); insert into TableA (id , fields) values (3, ''val3''); ......................... insert into TableA (id , fields) values (100, ''val100'');

Hiberate los agrupará en lotes de 50, y solo emitirá 2 SQL al DB, así:

insert into TableA (id , fields) values (1, ''val1'') , (2, ''val2'') ,(3, ''val3'') ,(4, ''val4'') ,......,(50, ''val50'') insert into TableA (id , fields) values (51, ''val51'') , (52, ''val52'') ,(53, ''val53'') ,(54, ''val54''),...... ,(100, ''val100'')

Tenga en cuenta que Hibernate inhabilitará la inserción de lotes en el nivel JDBC de forma transparente si la clave principal de la tabla de inserción es GenerationType.Identity .

Desde su registro: save() solo un registro y luego flush() , por lo que solo se agrega un INSERT SQL para cada descarga. Es por eso que Hibernate no puede ayudarte a insertar por lotes, ya que solo hay un INSERT SQL para procesar. Debe save() hasta la cantidad determinada de registros antes de llamar a flush() lugar de llamar a flush() para cada save() .

La mejor práctica de inserción de lotes es algo como esto:

Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<888888; i++ ) { TableA record = new TableA(); record.setXXXX(); session.save(record) if ( i % 50 == 0 ) { //50, same as the JDBC batch size //flush a batch of inserts and release memory: session.flush(); session.clear(); } } tx.commit(); session.close();

Guarda y purga los registros lote por lote. Al final de cada lote, debe borrar el contexto de persistencia para liberar algo de memoria para evitar el agotamiento de la memoria ya que cada objeto persistente se coloca en el primer nivel de caché (la memoria de su JVM). También podría desactivar la memoria caché de segundo nivel para reducir la sobrecarga innecesaria.

Referencia:


Si debe usar hibernate para grandes trabajos por lotes, StatelessSession es el camino a seguir. Reduce las cosas al mapeo de conversión de objetos-a-SQL más básico y elimina toda la sobrecarga de las características de ORM que no estás usando cuando solo atiborras filas al por mayor de DB.

También sería mucho más fácil hacer sugerencias sobre su código real que el registro :)


11:02:56.133 [main] DEBUG o.h.transaction.JDBCTransaction - commit

Esto significa que la base de datos se está comprometiendo después de cada inserción. Asegúrese de no comprometer su transacción / cerrar su sesión dentro del ciclo de inserción. Haga esto una vez al final en su lugar.