Issue
I'm facing some performance issues when batch inserting millions of records into Oracle.
So, I run some tests trying to understanding the best method to create the entities.
I'm curious why it is faster using hibernate generator than not using.
The scenarios:
- (auditAuto): With envers and Hibernate Generator (uuid2)
- (auditRandom): With envers and UUID.randomUUID().toString() as id
- (auditRandomOptLock): With envers and UUID.randomUUID().toString() as id, and Spring Boot @Version for optimistic lock
- (noAuditAuto): Without envers and Hibernate Generator (uuid2)
- (noAuditRandom): Without envers and UUID.randomUUID().toString() as id
- (noAuditRandomOptLock): Without envers and UUID.randomUUID().toString() as id, and Spring Boot @Version for optimistic lock
All entities are simples entities with two columns.
entity: id varchar2(255) primary key, name varchar2(255)
The results for 1.000.000 records:
Creating the collections:
- AuditAuto :: 192ms
- AuditRandom :: 1125ms
- AuditRandomOptLock :: 646ms
- NoAuditAuto :: 16ms
- NoAuditRandom :: 1694ms
- NoAuditRandomOptLock :: 841ms
Here, everything was as expected: Creating the entities collections was slower when using UUID.randomUUID() than not using for obvious reasons.
Saving the collections (each one in their own transaction)
- auditAutoRepository :: 216847ms
- auditRandomRepository :: 338461ms
- auditRandomOptLockRepository :: 370750ms
- noAuditAutoRepository :: 88616ms
- noAuditRandomRepository :: 155202ms
- noAuditRandomOptLockRepository :: 176575ms
Here is what I don't get. Ok... using envers is slower than not using (that was expected) (1, 2 and 3). But I don't get why using hibernate generator is faster at save (and commit).
As the id was already set at entities when using UUID.randomUUID() and, with generator, was not, I was expecting that the scenarios 5 and 6 to be faster than 4. But was not. Maybe because the amount of data transfered?
I run the scearios many times and I got consistent results.
I would like to read your opnion about it.
(Guys, the question is not about business rules if I need envers or not. It's a techinal curiosity about how things are handled in batch inserts).
Thank you.
Environment: Oracle 12c | Oracle JDK 1.8 | Spring Boot 1.5.4 | Hibernate 5.4
Solution
The answers I found:
Depending the way you do the batch insert, hibernate will not only do the insert, but execute others SQL.
Regarding my original question about me expecting 5 and 6 to be faster. I was right and wrong.
The scenario 5 was not supose to be faster, because it does a SELECT before the insert.
The scenario 6 was supose to be faster because it simple execute 1 insert and nothing else. Then problema was that, for the Optimistic Lock I was using @Version from spring and this one does not tell hibernate if the entity is or isn't persited. So, as scenario 5, it does execute a SELECT before.
The @Version to do it right should be imported from javax.persistence.
Bellow the queires hibernate executes for each scenarios and the right time spent (for 1 million records) using the correct @Version.
Thanks.
1. (auditAuto): With envers and Hibernate Generator (uuid2)
insert into teste.teste_audit_auto (name, id) values (?, ?)
select teste.hibernate_sequence.nextval from dual
insert into teste.version_control (timestamp, username, id) values (?, ?, ?)
insert into teste.teste_audit_auto_aud (revtype, name, id, rev) values (?, ?, ?, ?)
2. (auditRandom): With envers and UUID.randomUUID().toString() as id
select auditrando0_.id as id1_2_0_, auditrando0_.name as name2_2_0_ from teste.teste_audit_random auditrando0_ where auditrando0_.id=?
insert into teste.teste_audit_random (name, id) values (?, ?)
select teste.hibernate_sequence.nextval from dual
insert into teste.version_control (timestamp, username, id) values (?, ?, ?)
insert into teste.teste_audit_random_aud (revtype, name, id, rev) values (?, ?, ?, ?)
3. (auditRandomOptLock): With envers and UUID.randomUUID().toString() as id, and Spring Boot @Version for optimistic lock
insert into teste.teste_audit_random_opt_lock (name, opt_lock, id) values (?, ?, ?)
select teste.hibernate_sequence.nextval from dual
insert into teste.version_control (timestamp, username, id) values (?, ?, ?)
insert into teste.teste_audit_random_opt_lock_aud (revtype, name, id, rev) values (?, ?, ?, ?)
4. (noAuditAuto): Without envers and Hibernate Generator (uuid2)
insert into teste.teste_noaudit_auto (name, id) values (?, ?)
5. (noAuditRandom): Without envers and UUID.randomUUID().toString() as id
select noauditran0_.id as id1_7_0_, noauditran0_.name as name2_7_0_ from teste.teste_noaudit_random noauditran0_ where noauditran0_.id=?
insert into teste.teste_noaudit_random (name, id) values (?, ?)
6. (noAuditRandomOptLock): Without envers and UUID.randomUUID().toString() as id, and Spring Boot @Version for optimistic lock
insert into teste.teste_noaudit_random_opt_lock (name, opt_lock, id) values (?, ?, ?)
Creating the collections:
- AuditAuto :: 174ms
- AuditRandom :: 902ms
- AuditRandomOptLock :: 778ms
- NoAuditAuto :: 18ms
- NoAuditRandom :: 1584ms
- NoAuditRandomOptLock :: 808ms
Saving the collections (each one in their own transaction)
- auditAuto :: 355222ms
- auditRandom :: 350674ms
- auditRandomOptLock :: 385234ms
- noAuditAuto :: 114813ms
- noAuditRandom :: 119246ms
- noAuditRandomOptLock :: 74858ms
Answered By - mcardia
Answer Checked By - Robin (JavaFixing Admin)