コネクションプールって何?パフォーマンス観点から気にすること
バックエンドを勉強し始めて最近はデータベース周りに興味がでてきました。
最近読んでいるJavaパフォーマンスでデータベースに関するパフォーマンスの内容があったので、その個人的なゆるいメモです。
(Javaパフォーマンスめっちゃいい本だと思う。)
今回はJDBCのコネクションプールに関して。
そもそもコネクションプールって何?
アプリケーションからデータベースへ接続するためのオブジェクトを生成するには時間がかかってしまいます。
接続回数が多くてその度に多くの初期化コストがかかってしまう、という場合は パフォーマンスがよくないので1度作った接続オブジェクトを再利用することでパフォーマンスをあげましょうと。
「データベースの呼び出しが数回しかない場合、 JDBCの呼び出しにはStatementを使った方が全体最適化されるけど、 何度も呼び出す場合はPreparedStatementを使った方がよい」って話と関連していると思いました。
んで、再利用する接続オブジェクトはどこから提供されるの?って話で、提供しているのがコネクションプール。
コネクションプールのライブラリはたくさんあって、SpringBootを触っていたらHikariCPとかが身近なのかな。
プール自体はフレームワーク内に用意されることが多いっぽい。
プリペアードステートメントを使ってパフォーマンスを向上させるには、 接続オブジェクトがプールに置かれて再利用されることが必要。
そしてプールを適切に用意するにはコネクションプールとJDBCドライバーの設定に注意が必要。
なのでコネクションプールは大事。
パフォーマンス観点からのコネクションプールの考え方
細かなサイジングとかの話はここでは取り上げなくて、気を付けないといけないことや大きな原則をまとめてみます。
気を付けること
まず、コネクションプールの利用によりヒープの消費が激しくなるという問題を持っています。
コネクションプールには、接続オブジェクトだけでなく、接続ごとに用意されるプリペアードステートメントもキャッシュされる。
これらの接続オブジェクトやプリペアードステートメントのプールが占めるメモリ量がGCへの悪影響を及ぼさないように設定することが大事。
あと、データベース側とのバランスも大事。
データベースに接続するたびにデータベースのリソースをより多く消費してしまう。
アプリケーションサーバが多くの接続を開いたままだとデータベースのパフォーマンスが悪化してしまう。
ではどうするか
では原則としてどうするかの話。
- コネクションプールについてはアプリケーション内のスレッドごとに接続を1つ用意すること。
- アプリケーションサーバではスレッドプールとコネクションプールのサイズを同じにすること。
ただし、データベースがボトルネックになっている状況では逆効果になる可能性があります。 その場合は、コネクションプールを使って同時アクセスを制限することでパフォーマンスを改善できる可能性があります。
今回はここまで。