// JPA (Hibernate)
public List<User> findByName(String name) {
String jpql = "SELECT u FROM User u WHERE u.name = :name";
return em.createQuery(jpql, User.class)
.setParameter("name", name)
.getResultList();
}
// Spring Data JPA
List<User> findByName(String name);
[ 코드 ]
↓
Spring Data JPA (자동으로 리포지토리 구현)
↓
JPA (인터페이스)
↓
Hibernate (JPA 구현체)
↓
Database
- ExecutorType.BATCH는 MyBatis가 PreparedStatement를 재사용하도록 하여 성능을 향상시킨다.
- flushStatements()를 주기적으로 호출하여 메모리 사용을 조절합니다.
ExecutorType.BATCH 모드에서는 insert, update 등의 쿼리를 실행하면
MyBatis는 이를 JDBC의 PreparedStatement에 누적시킨다. 즉, session.flushStatements()를 호출하기 전까지는 실제로 DB에 쿼리가 실행되지 않고, 메모리에 저장돼 있다.
만약 BATCH_SIZE가 10만 건이라면?
10만 개의 SQL, 파라미터, 객체 상태가 JVM 힙 메모리에 계속 쌓여 있게 된다.
이게 누적되다 보면 결국 OutOfMemoryError가 발생할 수 있다.
foreach vs sqlsession
ExecutorType.BATCH 방식은 각각의 쿼리가 쌓여서 한 번에 실행되는 방식 따라서 foreach와 다르게 SQL 하나에 10만 줄짜리 쿼리가 만들어지지 않고
여러 PreparedStatement 객체가 한 번에 실행되기 때문에 SQL 문자열 길이가 문제가 되지 않는다
BATCH_SIZE : 100,000
업로드 건수
수행 시간
SqlSession(Executor.BATCH)
10만건
20초
30만건
64초
100만건
167초
for-each
10만건
7초
30만건
22초
100만건
68초
saveAll()
10만건
37초
30만건
103초
100만건
324초
찾아보기 - try-with-resources를 사용해서 SqlSession을 안전하게 닫습니다.
- 왜 안전하게 닫히는지
- foreach와 sqlsession의 sql문 자세하게 확인
- sql의 문자열 길이는 성능에 영향을 주는지 확인
AdminSalaryMapper mapper = session.getMapper(AdminSalaryMapper.class);
adminSalaryMapper.excelUploadWithSqlSession(salaries.get(i));
// 왜 mapper를 새로 만들어야 하는지??
// 무슨 원리인지 모르겠음
// 두 방식중에 효율적인것은?
// sqlsession은 아래 방시을 할수 밖에 없는건가?
for (int i = 0; i < totalSize; i += BATCH_SIZE) {
int endIndex = Math.min(i + BATCH_SIZE, totalSize);
List<Salary> batch = salaries.subList(i, endIndex);
adminSalaryMapper.excelUploadWithForeach(batch);
// 메모리 상태 출력
printMemoryUsage(i / BATCH_SIZE + 1);
}
for (int i = 0; i < totalSize; i++) {
mapper.excelUploadWithSqlSession(salaries.get(i));
if(i % BATCH_SIZE == 0) {
session.flushStatements(); // 쌓인 쿼리 실행
session.clearCache(); // 1차 캐쉬 제거
printMemoryUsage(i / BATCH_SIZE + 1);
}
}
org.apache.poi.util.RecordFormatException: Tried to read data but the maximum length for this record type is 100,000,000.
If the file is not corrupt and not large, please open an issue on bugzilla to request
increasing the maximum allowable size for this record type.
You can set a higher override value with IOUtils.setByteArrayMaxOverride()