Skip to main content Link Menu Expand (external link) Document Search Copy Copied

created at 2023-01-17

이전 테스트에서 발생한 성능이슈를 (1)Server 수평확장 및 (2)Docker 할당 리소스 추가로 10K HTTP request 테스트의 response까지 걸리는 시간110초에서 49초로 감소시켰다.

이번에는 Spring Jpa Batch를 통해 49초에서 23초로 감소시킨다.

NOTICE

쿼리튜닝이 아직 생소하기때문에 내용이 정확하지 않을 수 있습니다(특히 JDBC batch!). 혹시 잘못된 내용을 보신다면, ghkdqhrbals@gmail.com 로 메일주시면 정말정말 감사하겠습니다 :)

INDEX(의심가는 부분)

  1. AuthServer –> AuthDB 네트워크 오버로드
    1-1. 개선 결과(49초 -> 23초)
    1-2. 추가 고려점

1. AuthServer –> AuthDB 네트워크 오버로드

현재의 AuthServer은 JPA를 통해 AuthDB에 쿼리를 전송한다. 이 때, 하나의 쿼리를 반복전송 하게된다. 이는 다음의 가설을 정립시킨다.

  • 가설-1 : 도커 내부 네트워크를 너무 많이 사용하는 이유때문이 아닐까?

따라서 여러개의 쿼리를 모았다가 한번에 DB에 전송할 수 있는 JPA의 batch기능을 사용하고자 한다.

1-1. 개선결과(49초 -> 23초)

먼저 application.properties에 다음을 설정한다.

배치 사이즈를 너무 크게 잡아버리면, (1) 서버 다운시 전부 날라가버린다. (2) 잡아먹는 메모리가 크다. (3) DB종류에 따른 패킷 용량제한에 걸린다. 그래서 적절한 배치 사이즈를 설정해주어야 한다.

ex) MySQL는 최대 64MB 패킷까지만 듣는다. Postgres(9.5 버전 이후)는 1GB 까지 허용한다.

위 내용으로 미루어보면, (1) postgres를 쓰며, (2) insert user 쿼리길이가 짧은 필자는 50개가 적당하다고 판단!

spring.jpa.properties.hibernate.jdbc.batch_size=50
spring.jpa.properties.hibernate.order_inserts=true

이후 테스트해본 결과 49->23초의 개선결과를 확인할 수 있다. 즉, 가설-1이 타당하다라고 판단할 수 있다.

물론 JPA batch 기능은 multi-row insert가 아닌, 개별 쿼리를 모아서 전송하는 기능이다.

test-multiple-http-request | Request url: http://127.0.0.1:8080/auth/user
test-multiple-http-request | The number of HTTP Requests: 10000
test-multiple-http-request | The number of threads: 100
test-multiple-http-request | Proceeding! Please wait until getting all the responses
test-multiple-http-request | Elapsed Time: 23.889751999
test-multiple-http-request | Response status code:  200 , How many?:  10000

현재 user의 ID는 @GenerateID(Sequence) 어노테이션으로 생성하지 않는다. 따라서 Sequence를 계속해서 받아오는 성능이슈는 해당되지 않는다고 생각한다.

1-2. 추가 고려점

앞서 적용한 Batch는 단순히 개별 쿼리를 모아서 전송하는 기능이다. 그런데 이는 네트워크 통신에 소모되는 시간을 아껴준다 뿐이지, 실제 쿼리시간을 소모시킨다는 개념은 아니다. 따라서 실제 쿼리비용을 아껴줄 방법을 찾던중 다음의 표를 찾았다.

기능10건100건1000건10000건100000건
JPA0.03s0.19s2.06s18.47s175.58s
jdbc0.01s0.01s0.09s0.33s4.31s
JPA/jdbc 비율3192255.9640.73

reference : https://sabarada.tistory.com/220

JDBC로 직접 배치하게 되면 50배 이상의 속도를 낼 수 있다라고 볼 수 있다. 즉, JPA의 batch가 개별 insert를 모아서 전송하는 기능이라면, jdbc의 batch로 multi-row insert를 세부적으로 설정해줄 수 있다.

하지만 배치 중간에 에러가 발생할 경우를 심각하게 고려해야한다.

예로 배치된 여러 정상 쿼리 사이에 동일한 PK 값을 가지는 쿼리가 삽입되었다고 하자. 그러면, 트랜젝션 처리에 있어서 이 부분만 빼고 진행할 수가 없다…

그래서 이를 사전에 미리 파악해주는 로직이 들어가있어야지만 안정적으로 서비스할 수 있다.