Pgpool-II 4.1 新機能: シェアードリレーションキャッシュ【第7回】

この記事はPgpool-II 4.1の紹介【第1回】の中のシェアードリレーションキャッシュ 機能について詳しく紹介します。

リレーションキャッシュ

Pgpool-IIではクライアントから送られてきたクエリを解析し、クエリに含まれているテーブルや関数に関する情報をバックエンドのPostgreSQL上のシステムカタログから取得しています。
これらの取得した情報により柔軟なクエリレベルの負荷分散などの様々な機能が実現しています。
クエリが実行されるたびにシステムカタログを参照しに行くと無視できないオーバヘッドとなるため、各子プロセスでは1度取得した情報はローカルメモリにキャッシュしておきます。これをリレーションキャッシュと呼びます。
ローカルメモリに既に該当のシステムカタログ情報がキャッシュされている場合、それを直接使用することでこのオーバヘッドを軽減しています。

シェアードリレーションキャッシュ

Pgpool-IIの起動直後やPostgreSQLのフェイルオーバ処理後、その他各種設定により子プロセスが再起動した直後では子プロセスはローカルキャッシュを持っていません。そのため num_init_children が大きな値に設定されるような接続数が多いシステムの場合、子プロセスの数だけシステムカタログへの問い合わせが同時に発生し、このオーバヘッドが重なり大きくなる場合があります。

このような場合を想定して、Pgpool-II 4.1ではリレーションキャッシュをローカルキャッシュに加えて共有メモリにもキャッシュできる機能が追加されました。この機能は、デフォルトで有効(enable_shared_relcache=on)となります。
リレーションキャッシュはローカルキャッシュに加え、 memqcache_method(デフォルトは’shmem’) で指定されているキャッシュストレージに保存されます。
各子プロセスは、自身のローカルキャッシュにシステムカタログの情報が無ければ、キャッシュストレージを確認し、どちらにもなかった場合のみ、PostgreSQLのシステムカタログを参照します。その後、システムカタログから取得した情報は、自身のローカルキャッシュとキャッシュストレージの双方にキャッシュします。
つまり、いずれかの子プロセスが参照したシステムカタログはすべての子プロセスで共有されるため、上記のようなケースでも同じシステムカタログを参照する処理は1度で済むため、オーバヘッドをかなり抑えることができます。

ベンチマークによるシェアードリレーションキャッシュ機能の効果

PostgreSQL12とPgpool-II 4.1を用いた簡易なベンチマークテストを行いました。以下のグラフは、 enable_shared_relation_cache=off の場合と比較して enable_shared_relation_cache=on の場合に実行速度が相対的にどの程度向上しているかを表しています。この結果より、シェアードリレーションキャッシュ機能により2倍程度実行速度が向上していることが確認できました。

(テストコマンド)
pgbench  -C -T 30 -c 30 -n -f script_file

まとめ

今回は、Pgpool-II 4.1で追加されたシェアードリレーションキャッシュ機能について紹介しました。
この機能によりPgpool-II自体のオーバヘッドを軽減し、より快適に使用することができます。
特に num_init_children の設定値が大きい場合や、接続先のテーブル数が多い大規模な環境で効果が見込めるため、このような環境の場合Pgpool-II 4.1の使用を検討していただくと良いかと思います。