일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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
- 오라클 디비
- 티스토리
- oracle
- 자바 프로젝트
- gradle
- dynamic query
- 백준 알고리즘
- jsp
- 문법 정리
- MongoDB
- 유사코드
- 알고리즘
- hyperledger
- 초대장
- 운영체제
- smart cast
- auto configure
- 프로젝트
- 파이썬
- 리눅스
- SQL
- c#
- spring
- K6
- 학점
- JVM
- 파이썬 소스
- 자바
- 오라클
- resilience4j
Archives
- Today
- Total
모종닷컴
Batch Update 3편 본문
반응형
지난글에서 쿼리를 수정함으로써 아주 굉장한 효과를 보았습니다. 하지만 만족하지 않습니다.
고민 : 작업을 왜 하나의 스레드로만 하고 있었을까?
지금까지 Batch Update의 1편, 2편 모두 잘 보았더라면 결국 저희가 하고 있는 코드는 id가 1 ~ 1,000,000 인 데이터 행들을 일괄적으로 업데이트하는겁니다. 그렇다면 이런 생각을 해볼 수 있습니다. 왜 내가 이걸 스레드 하나로 돌리고 있어야 할까?? 여러 개의 스레드를 이용해서 각각 범위를 나누어 실행시키면 더 빠르지 않을까 하고 말이죠.
예를 들면 1~ 10000 은 스레드1이 담당하고 10001 ~ 20000는 스레드2가 담당하도록 한다면 동일한 행을 참고할 일도 없으니 여러 개의 스레드로 나누어서 실행해도 문제없을 것 같습니다. 일단 해보도록 하죠!
fun `스레드 두개로 테스트`() {
val executors = Executors.newCachedThreadPool()
val future1 = CompletableFuture.supplyAsync({ batchUpdate(1L, 500_000L) }, executors)
val future2 = CompletableFuture.supplyAsync({ batchUpdate(500_000L, 1_000_000L) }, executors)
CompletableFuture.allOf(future1, future2).join()
}
private fun batchUpdate(start: Long, end: Long) {
val rowMapper = RowMapper { rs, _ ->
LoginToken(
id = rs.getLong("id"), // 8
createdAt = LocalDateTime.parse(rs.getString("created_at"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) // 26
)
}
val chunkSize = 1000
(start until end).chunked(chunkSize) { subList ->
val selectLoginToken = "select * from login_token where id between ${subList.first()} and ${subList.last() + 1}"
val selected = jdbcTemplate.query(selectLoginToken, rowMapper).onEach {
it.expiredDt = it.createdAt!!.plusDays(7).toLocalDate()
}
val buffer = StringBuffer()
buffer.append("update login_token SET expired_dt = CASE\n")
selected.forEach { buffer.append("when id = ${it.id} then '${it.expiredDt.toString()}'") }
buffer.append("END WHERE id BETWEEN ${selected.first().id} and ${selected.last().id}")
jdbcTemplate.update(buffer.toString())
}
}
실행결과 20초가 소요되었습니다. 느낌상 스레드를 2개로 나누었으면 전보다 2배로 성능이 좋아져야 하는데 에잇..
3개로 늘려서 테스트해볼까요?
15초로 줄어든 모습입니다. 이제는 정말 만족하고 사용해도 될 것 같은 느낌입니다!-!
드디어 길고 길었던 저의 고민들과 고민들에 대한 저의 해결법을 다 적어보았습니다. 최초 9분이 걸리던 작업을 15초로 줄이기는 했지만 아직도 분명 더 성능을 끌어올릴수 있는 방법이 있을것만 같습니다. 훗날 좀 더 좋은 방법이 생각난다면 4편으로 다시 이어보도록 하겠습니다.
지금까지 긴 글 읽어주셔서 감사합니다 :)
반응형
'Programming' 카테고리의 다른 글
테스트 코드는 버그를 찢어 (0) | 2022.07.29 |
---|---|
Intellij Code Inspection 사용하기 (0) | 2022.07.24 |
우린 서로 다른 버전을 바라보고 있었어..(with 테이블과 엔티티) (0) | 2022.07.20 |
Batch Update 2편 (0) | 2022.05.07 |
Batch Update 1편 (0) | 2022.04.30 |