성능 향상을 위한 Hikari Connection Pool 설정 for MySQL (1)
Hikari Connection Pool
DataSource 쪽 디버깅을 하다 보면 자주 접했던 이름이지만, 정확히 뭔지는 몰랐다.
2.0 버전부터, Spring Boot의 기본 DataSource로 사용되고 있는 Connection Pool 프레임워크이다.
더 정확히 말하자면, spring-boot-starter-jdbc 또는 spring-boot-starter-data-jpa "starters"를 사용하는 경우
자동적으로 Hikari CP에 대한 의존성 설정이 된다고 한다.
DataSource?
Connection Pool을 사용하면 미리 정해진 수만큼의 커넥션을 Pool에 만들어두고, 필요할 때마다 이를 꺼내 쓰고 반환한다.
커넥션은 생성 비용이 크기 때문에, 이와 같은 방식으로 연결 비용을 줄여, 빠르게 DB에 접속할 수 있다.
DriverManager가 아닌 DataSource를 통해야 이런 커넥션 풀링을 할 수 있다.
(분산 트랜잭션도 DriverManager로는 할 수 없다고 한다.)
DataSource는 DriverManager와 데이터베이스 사이에 JNDI 라는 기술을 추가한 것을 추상화한 인터페이스라고 한다.
Spring Boot에서 다른 DataSource를 사용하고 싶다면 DataSourceBuilder를 통해 얻을 수 있고, 그 종류는 아래와 같다.
물론 나는 당장 다른 Connection Pool을 써볼 이유가 없지만, 알아둬도 나쁘진 않을 것 같다.
- HikariCP
- Tomcat pooling Datasource
- Commons DBCP2
- Oracle UCP & OracleDataSource
- Spring Framework’s SimpleDriverDataSource
- H2 JdbcDataSource
- PostgreSQL PGSimpleDataSource
- C3P0
Hikari CP 설정 옵션
아래 공식 문서 링크를 보면, 설정 방법이 상세하게 나와있다.
https://github.com/brettwooldridge/HikariCP#rocket-initialization
GitHub - brettwooldridge/HikariCP: 光 HikariCP・A solid, high-performance, JDBC connection pool at last.
光 HikariCP・A solid, high-performance, JDBC connection pool at last. - GitHub - brettwooldridge/HikariCP: 光 HikariCP・A solid, high-performance, JDBC connection pool at last.
github.com
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/simpsons");
config.setUsername("bart");
config.setPassword("51mp50n");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
HikariDataSource ds = new HikariDataSource(config);
위와 같은 설정 예시를 볼 수 있다. 아래처럼, properties 파일 자체를 전달하거나 설정 파일의 위치를 지정할 수도 있다.
// Examines both filesystem and classpath for .properties file
HikariConfig config = new HikariConfig("/some/path/hikari.properties");
HikariDataSource ds = new HikariDataSource(config);
또, 공식문서에서는 JdbcUrl 대신 dataSourceClassName을 사용하는 것을 권장하는 것을 알 수 있었다.
(class 경로가 달라질 수 있기 때문일까?)
그러나 Spring Boot의 auto-configuration을 이용하고 있다면, JdbcUrl로 설정해야 한다고 한다.
그래서 사실, 일반적으로 해당되는 내용은 아니다.
MySQL 기준 추천 설정
그럼 어떤 옵션이 있고, 어떻게 값을 설정하면 좋을지 살펴보자. 각 옵션의 기본값은 DB 벤더 사마다 다른 것으로 보인다.
나는 프로젝트에 MySQL을 쓰고 있기 때문에 MySQL을 기준으로 정리해보겠다.
친절하게도 Hikari CP 공식문서에서 MySQL 추천 설정 값을 알려주고 있다.
https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
MySQL Configuration
光 HikariCP・A solid, high-performance, JDBC connection pool at last. - brettwooldridge/HikariCP
github.com
cachePrepStmt
명령문(Prepared Statement)을 캐시할지 결정한다. MySQL 기본값은 false이므로 true로 설정하는 것을 추천한다.
prepStmtCacheSize
DB Driver가 Connection 당 캐시할 명령문(Prepared Statement)의 수를 설정한다. MySQL 기본값은 25이다.
250 ~ 500 사이 값을 추천한다.
prepStmtCacheSqlLimit
DB Driver가 캐싱할 명령문의 최대 길이를 지정한다. MySQL 기본값은 256이다.
2048를 추천한다고 한다. (특히 ORM을 사용한다면, 경험 상 기본값은 턱없이 모자라다고 함)
useServerPrepStmts
최신 MySQL(4.1, 5.0 ~)은 Server-side prepared statements를 지원한다. 하지만 기본값은 false이다.
이 설정을 true로 하면 성능을 더 향상시킬 수 있다고 한다.
Server-side prepared statement란?
Client prepared statement는 (바인딩 변수에 값을 매핑한) 하나의 완성된 SQL 문장을 MySQL 서버에 전송하는 반면,
Server prepared statement는 JDBC가 바인딩할 값만 서버로 보내면, MySQL 서버가 분석된 쿼리 정보에 값을 바인딩하여 쿼리를 실행하는 것이다.
이에 더불어 그 외의 옵션과, MySQL 기준의 기본 값, 추천 값을 잘 정리해준 블로그가 있어서 링크로 첨부한다.
https://2ssue.github.io/programming/HikariCP-MySQL/
HikariCP를 MySQL에 맞게 튜닝하기
Spring Boot로 프로젝트를 하다가 MySQL의 성능을 향상시켜야하는 일이 있었다. 어떤 데이터를 로딩 할 때 DB의 연결이 모자라 가끔 연결을 대기하는 상황이 있었는데, 연결이 항상 모자란건 아니라
2ssue.github.io
Pool Size는?
그런데, 이건 커넥션 풀인데 그래서 pool size는 몇으로 설정하는 게 좋은걸까?
이 부분은 다음 포스팅에서 정리해보겠다.