こんにちは、GMOアドマーケティング インフラ開発部のhakumaiです。
前回の記事「AWSエンジニアがGCPメインの会社に転職してみた」を読んでいただいた方々、ありがとうございます。
今回は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全体で使用するメモリ量については、
1 |
共有メモリ + プロセスメモリ |
となります。
PostgreSQLのメモリの設定項目について
共有メモリ
shared_buffers
テーブルやインデックスのデータをキャッシュしておくための領域。サーバの総メモリの1/4程度の値で設定する。
wal_buffers
ディスクに書き込まれていないWAL(トランザクションログ)をキャッシュしておくための領域。
WALはトランザクションのコミット毎にディスクに書き込まれるため、shared_buffersの1/32程度の値で設定する。
また、PostgreSQL 9.1以降は自動的に調整されるため明確な値は設定する必要はない。
プロセスメモリ
work_mem
クエリ実行時にソートやハッシュ処理のために使われる領域。
バックエンドプロセスごとに確保されるため、接続数とクエリで扱うデータのサイズとの兼ね合いで設定する。
さらに、複雑なクエリの場合は1クエリを実行するためにソートやハッシュ処理が並行して複数回実行されるため注意。
以下を参考に設定する。
1 |
( サーバ総メモリ - (shared_buffers + PortgreSQL以外で使用するメモリ) ) / max_connections |
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に向き合ってがんばっていこうと思います。
GMOアドマーケティングのインフラエンジニア。(♀)
クラウドインフラのアーキテクチャ設計が得意です。
アプリ開発もできます。
白米と服とおいしいものとFPSと技術が好きです。