Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 인프콘 2024
- JavaScript
- 디자인 패턴
- 개발자부트캠프추천
- 빈 조회 2개 이상
- 전략패턴 #StrategyPattern #디자인패턴
- Python
- 코딩테스트 준비
- infcon 2024
- Spring multimodule
- 취업리부트코스
- 프로그래머스 이중우선순위큐
- DesignPattern
- 프로그래머스
- 빈 충돌
- 단기개발자코스
- 커스텀 헤더
- 99클럽
- @FeignClient
- jwt
- 항해99
- 디자인패턴
- 파이썬
- spring batch 5.0
- 1주일회고
- TiL
- KPT회고
- 구글 OAuth login
- 개발자 취업
- jwttoken
Archives
- Today
- Total
m1ndy5's coding blog
Ditto 프로젝트 종목 불러오기 with batchUpdate 본문
Toy Projects/Ditto - Discuss Today's Topic
Ditto 프로젝트 종목 불러오기 with batchUpdate
정민됴 2024. 2. 29. 21:48코스피와 코스닥 종목을 가져오면서 해당 종목의 개수가 거의 4000개에 가까웠고 각 종목의 10일치 데이터만 가져온다고 해도 거의 40000개의 쿼리가 날라가야하는 상황이었다. JPA saveAll()를 사용해도 bulk insert 는 되지 않았기 때문에 jdbcTemplate의 batchUpdate를 사용하여 bulk insert를 처리하였다.
일단 나는 Mysql 8.0을 사용하고 있기 때문에
DATABASE_URL=jdbc:mysql://{rds 주소}/ditto?&rewriteBatchedStatements=true
이렇게 스키마 뒤에 &rewriteBatchedStatements=true 를 붙여주었다.
JPA saveAll()과 JdbcTemplateBatchUpdate() 성능 비교
BatchUpdate 기준
package org.example.repository;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.time.StopWatch;
import org.example.domain.Company;
import org.example.domain.PricePerDay;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.List;
@Repository
@RequiredArgsConstructor
public class PriceBulkRepository {
private final JdbcTemplate jdbcTemplate;
@Transactional
public void saveAll(List<PricePerDay> pricePerDays){
String sql = "INSERT INTO PricePerDay (company_id,date,high_price,last_price,low_price,start_price,trading_volume) " +
"VALUES (?, ?, ?, ?, ?, ?, ?)";
jdbcTemplate.batchUpdate(sql,
new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
PricePerDay pricePerDay = pricePerDays.get(i);
ps.setLong(1, pricePerDay.getCompanyId());
ps.setDate(2, Date.valueOf(pricePerDay.getDate()));
ps.setInt(3, pricePerDay.getHighPrice());
ps.setInt(4, pricePerDay.getLastPrice());
ps.setInt(5, pricePerDay.getLowPrice());
ps.setInt(6, pricePerDay.getStartPrice());
ps.setLong(7, pricePerDay.getTradingVolume());
}
@Override
public int getBatchSize() {
return pricePerDays.size();
}
});
}
}
package org.example.config;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.domain.PricePerDay;
import org.example.repository.PriceBulkRepository;
import org.springframework.batch.item.Chunk;
import org.springframework.batch.item.ItemWriter;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Slf4j
@RequiredArgsConstructor
public class FiveYearPriceItemWriter implements ItemWriter<List<PricePerDay>> {
private final PriceBulkRepository priceBulkRepository;
@Override
public void write(Chunk<? extends List<PricePerDay>> chunk) throws Exception {
long startTime = System.currentTimeMillis();
int total = chunk.getItems().get(0).size();
for (int i = 0; i < total; i+=999){
if (i+999 > chunk.getItems().get(0).size()){
priceBulkRepository.saveAll(chunk.getItems().get(0).subList(i, total-1));
} else {
log.info(String.valueOf(i));
priceBulkRepository.saveAll(chunk.getItems().get(0).subList(i, i + 999));
}
}
long stopTime = System.currentTimeMillis();
log.info("코드 실행 시간: " + (stopTime - startTime));
}
}
총 36963개보다 조금 넘고 1598 밀리초가 걸렸다.
JPA saveAll() 기준
똑같은 개수 기준 JPA saveAll()은 352261밀리초가 걸렸다.
와우 정말 생각보다 차이가 많이 나서 놀랐다.
결론
대용량 데이터 저장에는 JPA saveAll()이 아닌 JDBC BatchUpdate()를 사용하자!!
'Toy Projects > Ditto - Discuss Today's Topic' 카테고리의 다른 글
Ditto 프로젝트 동시성 문제 해결하기 3편 - 낙관적 락 Version, Select for Update (0) | 2024.03.13 |
---|---|
Ditto 프로젝트 docker-compose 1편 - Docker란, Docker Cache, Docker Network (0) | 2024.03.07 |
Ditto 프로젝트 N+1 문제 2편 - N+1 문제 해결과 외래키 (2) | 2024.02.27 |
Ditto 프로젝트 N+1 문제 1편 - FetchType Lazy, Eager (0) | 2024.02.26 |
Ditto 프로젝트 동시성 문제 해결하기 2편 - 낙관적 락을 사용해 동시성 해결하기 (feat. Deadlock, DirtyChecking, Retry) (1) | 2024.02.24 |