PostgreSQLのメモリアーキテクチャを知る

こんにちは、GMOアドマーケティング インフラ開発部のhakumaiです。

前回の記事「AWSエンジニアがGCPメインの会社に転職してみた」を読んでいただいた方々、ありがとうございます。

初めまして、GMOアドマーケティング インフラ開発部のhakumaiです。今年1月にHRTech系企業からGMOアドマーケティングに転職してきました。現職では、女子向けメディア「めるも」のインフラ業務に携わり、日々業務に励んでおります。今回は、私が転職してみて感じたインフラ技術のギャップの一部についてお話しいたします。 前職でのインフラ環境・経験について前職のHRTech企業で触っていたインフラ環境は、ほぼAWSでした。インフラの保守運用業務に加え、新規プロダクトのインフラアーキテクチャ設計構築を経験したこともあり、V...

 

今回は2回目の投稿になります。

前回と同様に、「AWSエンジニアから見たGCP」のような記事を書こうと思っていましたが、

最近業務で触れたPostgreSQLのメモリ周りの話があまりにも濃かったので、

今回はPostgreSQLのメモリアーキテクチャを題材にお話しいたします。

(「AWSエンジニアから見たGCP」の続編は次回以降改めて執筆いたします。)

 

hakumaiのデータベース運用経験について

前職で運用していたプロダクトはPostgreSQLを利用していて、現職で運用しているプロダクトも同じくPostgreSQLを利用しています。

現職で運用しているプロダクトのDBサーバは、GCEにPostgreSQLをインストールし構築したものを利用しています。

しかし、前職ではAWSのRDSというマネージドRDBサービスを利用しPostgreSQLを運用していたので

PostgreSQLの細かな設定に関してはRDS側で自動で調整し設定してくれており、

PostgreSQLの設定ファイル(postgresql.conf)内の各設定値については今まで細かく見たことがない状態でした。

もちろんメモリ周りの設定値についても、RDSインスタンスのメモリを設定するのみでRDSが良しなにやってくれており

恥ずかしながら直接メモリ周りの設定値にはほぼ触れることはありませんでした。

このような状況もあり、DB関連の話についてはなんとなく苦手意識も持っていました。

 

向き合わなければならない機会は突然やってくる

そんなある日、現在運用しているプロダクトのDBサーバが突然高負荷になったのです。

原因のひとつとして、PostgreSQLのメモリ設定を含めDBサーバのメモリ設定が適切でないことが判明しました。

そのプロダクトのインフラメイン担当は私…、知見を広げる良い機会だと考え、きちんと向き合うことになりました。

 

PostgreSQLのメモリの種類について

PostgreSQLのメモリには大きく分けて以下2つあります。

共有メモリ

PostgreSQLサーバ全体で共有されるメモリ。PostgreSQLの起動時に確保されるもの。

プロセスメモリ

バックエンドプロセスが起動するときに確保される作業用のメモリ。

また、PostgreSQL全体で使用するメモリ量については、

となります。

 

PostgreSQLのメモリの設定項目について

共有メモリ

shared_buffers

テーブルやインデックスのデータをキャッシュしておくための領域。サーバの総メモリの1/4程度の値で設定する。

wal_buffers

ディスクに書き込まれていないWAL(トランザクションログ)をキャッシュしておくための領域。

WALはトランザクションのコミット毎にディスクに書き込まれるため、shared_buffersの1/32程度の値で設定する。

また、PostgreSQL 9.1以降は自動的に調整されるため明確な値は設定する必要はない。

 

プロセスメモリ

work_mem

クエリ実行時にソートやハッシュ処理のために使われる領域。

バックエンドプロセスごとに確保されるため、接続数とクエリで扱うデータのサイズとの兼ね合いで設定する。

さらに、複雑なクエリの場合は1クエリを実行するためにソートやハッシュ処理が並行して複数回実行されるため注意。

以下を参考に設定する。

temp_buffers

クエリ実行時に、一時テーブル(CREATE TEMP TABLE文の実行)へアクセスする時のみ使われる領域。

maintenance_work_mem

メンテナンスコマンド(VACUUM, CREATE INDEX, ALTER TABLE ADD FOREIGN KEYなど)の実行時に使われる領域。

 

その他

effective_cache_size

PostgreSQLが使用するバッファ領域の大きさを推定するために設定する値。

高い値を設定するとインデックススキャンが使用されるようになり、低い値を設定するとシーケンシャルスキャンが使用されるようになる。

推定目的で使用される値で、実メモリの確保や消費されることはない。

サーバの総メモリの1/2程度の値で設定する。

 

PostgreSQLメモリ構成概要図

ここまでの話をおおまかに図にすると以下のようになります。

なんとなくではありますが、イメージが湧いてきたのではないでしょうか。

 

おわりに

簡単ではありますが、PostgreSQLのメモリ周りのアーキテクチャについて紹介しました。

自分の中で咀嚼するまでにいろいろなドキュメントを読み込むなどしてちょっと時間はかかりましたが、

咀嚼できた瞬間は「PostgreSQLとちょっと仲良くなれたかも」と人生で初めて感じました。

今回お話ししたことを踏まえて、現在実際にメモリ周りの設定値のチューニングを行っていますが、

将来的にはCloud SQLへ移行する予定なので引き続きDBに向き合ってがんばっていこうと思います。