크게 잡으면 좋을 것 같지만
동시 요청이 몰리면 커넥션 풀을 키우고 싶어진다. 대기가 줄어들 것 같기 때문이다. 하지만 대개 반대다.
풀 크기는 애플리케이션이 DB에 동시에 얼마나 많은 일을 시킬 것인가를 정하는 값이다. DB가 실제로 병렬 처리할 수 있는 양을 넘어서면, 넘긴 만큼은 DB 안에서 줄을 선다. 대기 장소가 애플리케이션에서 DB로 옮겨갔을 뿐이고, 그 과정에서 컨텍스트 스위칭과 락 경합이 늘어 오히려 느려진다.
DB가 동시에 할 수 있는 일의 양
DB의 병렬성은 대략 두 가지가 정한다.
- CPU 코어 수 — 계산과 인덱스 탐색
- 디스크 병렬성 — 동시에 처리 가능한 I/O 수
HikariCP 문서가 제안하는 출발점은 이렇다.
connections = (core_count * 2) + effective_spindle_count
코어 8개에 SSD 한 대라면 열몇 개 남짓이다. 흔히 잡는 100보다 훨씬 작다.
Little’s Law로 가늠하기
대기 이론의 관계식 하나면 감을 잡을 수 있다.
L = λ × W
동시 처리 수 = 초당 처리 요청 수 × 요청당 소요 시간
초당 500건을 처리하고 쿼리 하나가 평균 10ms라면,
L = 500 × 0.01 = 5
이론상 커넥션 5개면 감당된다. 여유를 더해도 10~20 수준이다.
이 계산이 알려주는 것
식을 뒤집어 보면 더 중요한 사실이 나온다. W(쿼리 시간)를 줄이는 것이 L(풀 크기)을 늘리는 것보다 훨씬 강력하다. 쿼리를 10ms에서 2ms로 줄이면 같은 커넥션으로 다섯 배를 처리한다.
풀을 늘리고 싶어질 때는 보통 느린 쿼리가 원인이다. 풀 크기는 증상을 가리는 손잡이에 가깝다.
정리
- 풀은 DB의 병렬 처리 능력에 맞춘다. 요청 수에 맞추는 게 아니다
- 작게 시작해서 대기 시간을 측정하며 올린다
- 대기가 길다면 먼저 쿼리를 의심한다