문서의 이전 판입니다!
Batch Insert는 여러건의 insert
문을 insert into xxx (…) values(…), (…), (…)
로 바꿔줌으로써 성능을 향상 시킬 수 있다.
GenerationType.IDENTITY
ID에 대해서는 Batch Insert가 작동하지 않는다. ID를 리턴받아 Entity 객체에 채워줘야 하기 때문으로 보인다.insert into xxx (…) values(…), (….), ….
형태로 합쳐주는 것이 아니다.PreparedStatement#execute(String)
으로 쿼리를 실행하는데, batch 모드가 되면 JDBC 표준 PreparedStatement#addBatch(String) 메소드를 호출해주는 것 뿐이다.session.flush()
를 호출한다는 것은 Statement.executeBatch()
를 호출한다는 의미인 듯 하다.addBatch
로 들어온 insert 문을 하나로 합쳐주는 기능을 가진 것들이 있는데 이를 활성화 시켜줘야만 작동한다.rewriteBatchedStatements=true
옵션을 추가해주면 된다.logger=com.mysql.jdbc.log.Slf4JLogger&profileSQL=true
옵션으로 로그를 통해 확인할 수 있다.<prop key="hibernate.jdbc.batch_size">[동시 Insert 갯수]</prop>
session.flush(); session.clear();
호출session.clear()
를 호출하는 이유는, insert 된 데이터들이 First Level Cache 메모리에 남아 있어서 메모리 고갈 발생할 수 있기 때문이다.org.hibernate.jdbc.AbstractBatcher
에서 남기는 로그 확인public void doBatch() { Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); Cart cart = new Cart(...); customer.setCart(cart) // note we are adding the cart to the customer, so this object // needs to be persisted as well session.save(customer); if ( (i + 1) % 20 == 0 ) { //20, same as the JDBC batch size //flush a batch of inserts and release memory: session.flush(); session.clear(); } } tx.commit(); session.close(); }
Customer-Cart
가 연관 관계가 있어서 하나의 Customer
insert 후에 곧바로 Cart
가 insert되고, 그 다음에 다시 Customer
가 insert 되기 때문에 Customer는 Customer끼리, Cart는 Cart끼리 묶이지 않기 때문이다.<prop key="hibernate.order_inserts">true</prop> <prop key="hibernate.order_updates">true</prop>