🐕

PostgreSQLのメモリたち

2025/02/20に公開

Daily Blogging61日目

PostgreSQLにたくさんのプロセスがいた

メモリもたくさん領域があるよ

全体像

メモリは、サーバプロセス全体で共有される共有メモリ域とバックエンドプロセスで確保されるプロセスメモリ域の大きく二つに分けられる。

共有メモリ域

ライタプロセスとかWALライタプロセスなどのバックグラウンドプロセスと、
SQLクエリを実行するバックエンドプロセスの全てから参照、更新される領域。

この領域はサーバ起動時にOSが確保してくれる。

共有メモリ域は複数の領域に分かれるよ

共有バッファ(shared_buffers)

テーブルの使用頻度の高いデータや、インデックスでよく通過されるノードがキャッシュされる領域。
ここにキャッシュしておくことで、ディスクI/Oを削減することができ、パフォーマンスが上がる。

WALバッファ(wal_buffers)

ディスクにまだ書き込まれていなトランザクションのログ(WAL; Write Ahead Logging)をキャッシュする領域。

空き領域マップ(Free Space Map)

テーブル上の利用可能領域を示す情報を扱う領域。

vacuum処理の時には、デッドタプルを回収してその領域を空き領域とする。
レコードの追加、更新時にはこの空き領域マップを参考に、空いている領域にレコードを挿入していく。
ソートなしでレコードを取得する時に順番がバラバラなのはこれも一因。

可視性マップ(Visibility Map)

各テーブルのページ単位でそのページ内のすべてのタプルが可視状態かを管理する情報を扱う領域。
可視状態:削除フラグが付与されていないレコード(論理削除されていない状態)

vacuum時にスキャンをスキップできるページを判断するために利用される。

インデックスオンリースキャンの時にも利用されるよ
インデックスだけをみてもその値が可視状態なのか判断がつかないので、結局ディスクにアクセスする必要があるが、可視性マップを参照することでディスクへのアクセスなしでその値が可視状態であるかを判断できる。
→高速な検索を実現

vacuum時やレコードの更新時に可視性マップも更新される。

プロセスメモリ

バックエンドプロセスごとに確保される作業用メモリ。
確保したプロセスからのみ参照可能

作業用メモリ(work_mem)

クエリ実行時に、並び替えやハッシュテーブル操作で使われる領域。
このメモリを調整すると並び替えとかの性能アップの可能性あり。

一つのクエリで複数回の並び替えなどが発生する場合は、その分だけこのメモリが確保される。

メンテナンス作業用メモリ(maintenance_work_mem)

vacuum、インデックス作成、外部キー追加などのDBメンテナンス系の作業で使用する領域。

メンテナンス時間を短縮したい場合は、この領域をwork_memより大きくすると良い。

一時バッファ(tmp_buffers)

バックエンドプロセスごとに作成される一時テーブルのデータをキャッシュするための領域。

まとめ

メモリを知るとどういう機能がそれぞれどう噛み合っているのかがちょっとわかるようになるね

Discussion