HikariCP is a simple, solid, high-performance, “zero-overhead” production ready JDBC connection pool at last. At roughly 130Kb, the library is very light.
Configuring a connection pool is something that developers often get wrong. There are several, possibly counter-intuitive for some, principles that need to be understood when configuring the pool.
When we look at what the major bottlenecks for a database are, they can be summarized as three basic categories: CPU, Disk, Network. We could add Memory in there, but compared to Disk and Network there are several orders of magnitude difference in bandwidth.
Don’t over-provision your database. The formula below is provided by the PostgreSQL project as a starting point, but I believe it will be largely applicable across databases. You should test your application, i.e. simulate expected load, and try different pool settings around this starting point:
Don’t be tricked into thinking, “SSDs are faster and therefore I can have more threads”. That is exactly 180 degrees backwards. Faster, no seeks, no rotational delays means less blocking and therefore fewer threads [closer to core count] will perform better than more threads. More threads only perform better when blocking creates opportunities for executing.
postgres=# show tcp_keepalives_idle; tcp_keepalives_idle --------------------- 0 (1 row)
postgres=# show tcp_keepalives_interval; tcp_keepalives_interval ------------------------- 0 (1 row)
postgres=# show tcp_keepalives_count; tcp_keepalives_count ---------------------- 0 (1 row)
postgres=# show idle_in_transaction_session_timeout; idle_in_transaction_session_timeout ------------------------------------- 0 (1 row)
postgres=# alter system set tcp_keepalives_idle=10; ALTER SYSTEM postgres=# alter system set tcp_keepalives_interval=2; ALTER SYSTEM postgres=# alter system set tcp_keepalives_count=3; ALTER SYSTEM postgres=# alter system set idle_in_transaction_session_timeout='10s'; ALTER SYSTEM postgres=# postgres=# SELECT pg_reload_conf(); pg_reload_conf ---------------- t (1 row)
postgres=# show idle_in_transaction_session_timeout; idle_in_transaction_session_timeout ------------------------------------- 10s (1 row)
postgres=# show tcp_keepalives_count; tcp_keepalives_count ---------------------- 0 (1 row)
postgres=# show tcp_keepalives_interval; tcp_keepalives_interval ------------------------- 0 (1 row)
postgres=# show tcp_keepalives_idle; tcp_keepalives_idle --------------------- 0 (1 row)
postgres=# show tcp_keepalives_idle; tcp_keepalives_idle --------------------- 10 (1 row)
postgres=# show tcp_keepalives_interval; tcp_keepalives_interval ------------------------- 2 (1 row)
postgres=# show tcp_keepalives_count; tcp_keepalives_count ---------------------- 3 (1 row)
postgres=# show idle_in_transaction_session_timeout; idle_in_transaction_session_timeout ------------------------------------- 10s (1 row)
Get Rid of Staled Connections
1 2 3 4 5 6 7 8 9 10 11 12 13
select clock_timestamp(), datname, pid, state, application_name, state_change from pg_stat_activity;
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname ='regress' AND pid <> pg_backend_pid() AND state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled') AND application_name !~'(?:psql)|(?:pgAdmin.+)' AND state_change <current_timestamp-INTERVAL'5'MINUTE;
select statement_timestamp(), datname, pid, state, application_name, state_change from pg_stat_activity;
select clock_timestamp(), datname, pid, state, application_name, state_change from pg_stat_activity;