メモリ管理
共有メモリ域
-
共有メモリ域
- サーバプロセス全体
共有バッファ(shared_buffers)
-
PostgreSQL起動時にLinuxのカーネルパラメータ
shmmax
と比較shmmax
よりもshared_buffers
が大きいとエラー- カーネルパラメータ
docker exec -it -u postgres b612ca6e cat /proc/sys/kernel/shmmax
- でかい
18446744073692774399
shared_buffers
設定の確認
postgres=# SELECT name,setting,unit,context FROM pg_settings WHERE name='shared_buffers';
name | setting | unit | context
----------------+---------+------+------------
shared_buffers | 16384 | 8kB | postmaster
(1 row)
WALバッファ(wal_buffers)
postgres=# SELECT name,setting,unit,context FROM pg_settings WHERE name='wal_buffers';
name | setting | unit | context
-------------+---------+------+------------
wal_buffers | 512 | 8kB | postmaster
(1 row)
- ディスクに書き込まれていないトランザクションログ(WAL: Write Ahead Logging)をキャッシュする領域
空き領域マップ(Free Space Map)
- 公式
-
リレーション上の利用可能な領域を追跡する領域
- ハッシュインデックス以外
/docker:b612ca6e:/var/lib/postgresql/data $ ls base/1/
112 2601_fsm 2663 3080 3607
113 2601_vm 2664 3081 3608
1247 2602 2665 3085 3609
1247_fsm 2602_fsm 2666 3118 3712
- この
_fsm
サフィックス付きのファイルがそれ - pg_freespacemapモジュールでFSMの情報を確認できる
可視性マップ
-
バキュームの高速化用
- 処理が必要な処理か否かを可視性マップで判断
- インデックスオンリースキャン、カヴァリングインデックス
-
heap
- テーブルのメインのデータ領域
-
普通のインデックススキャンは、indexにアクセスしたあとheapにもアクセスする
- indexとheapを行き来してheapにランダムアクセスするので遅い
-
PostgreSQLはindex only scanをサポートしている(9.2~)
- indexに必要な情報が全部あればheapアクセスしない
-
使用条件
-
インデックスから元のデータを得られること
- B-tree, GiSTはOK
- ほかのはだめ
- クエリがインデックス中のカラムだけを参照していること
-
-
さらに、取得される各行がMVCCスナップショットから見えていること
- 可視性情報はindexには保持されておらず、heapにのみ保持されている
- ではheapをいちいち見ないといけないか、というとそんなことはない
-
heapを見に行く代わりに「可視性マップ」のビットを見る
- ビットが立っていたらインデックスのデータをそのまま返す
- ビットが立っていなければ、heapを見に行く
- 可視性マップはheapよりも容量が4桁くらい小さいのでI/Oが少なくて済む
_vm
ってやつ
112 2601_fsm 2663 3080 3607
113 2601_vm 2664 3081 3608
1247 2602 2665 3085 3609
1247_fsm 2602_fsm 2666 3118 3712
プロセスメモリ
- バックエンドプロセスで確保
- = クライアントとの接続ごと
-
なので、contextは
user
- 一般ユーザのSET文で設定変更できる
作業メモリ(work_mem)
postgres=# SELECT name,setting,unit,context FROM pg_settings WHERE name='work_mem';
name | setting | unit | context
----------+---------+------+---------
work_mem | 4096 | kB | user
(1 row)
- 1クエリにつきこれだけ、ではない
-
1クエリの中で作業メモリを使うような処理が複数あれば、処理ごとに設定した領域が確保される
- サブクエリとか
-
ソート、ハッシュテーブル操作で使用
- 暗黙のソートが走るDISTINCT
- merge join, hash joinとか
- システム全体のメモリ圧迫に注意する
メンテナンス用作業メモリ(maintenanceworkmem)
postgres=# SELECT name,setting,unit,context FROM pg_settings WHERE name='maintenance_work_mem';
name | setting | unit | context
----------------------+---------+------+---------
maintenance_work_mem | 65536 | kB | user
(1 row)
-
メンテナンス作業とは
- VACUUM
- CREATE INDEX
- ALTER TABLE ADD FOREIGN KEY
- 同時にたくさん実行する代物ではないので
work_mem
より大きくても大丈夫 -
autovacuum使用時はこの値 ×
autovacuum_max_workers
が確保されるので注意-
autovacuum_work_mem
でautovacuum
ワーカプロセスごとのメモリ量を上書きできる- デフォルト
-1
だとmaintenace_work_mem
が代わりに使用される
- デフォルト
-
postgres=# SELECT name,setting,unit,context FROM pg_settings WHERE name='autovacuum_work_mem';
name | setting | unit | context
---------------------+---------+------+---------
autovacuum_work_mem | -1 | kB | sighup
(1 row)
一時バッファ(temp_buffers)
postgres=# SELECT name,setting,unit,context FROM pg_settings WHERE name='temp_buffers';
name | setting | unit | context
--------------+---------+------+---------
temp_buffers | 1024 | 8kB | user
(1 row)
- 一時テーブルにアクセスするときに用いられるメモリ領域
-
そのセッションで一時テーブルを利用する前なら、一般ユーザのSET文で設定変更できる
- ひとたび一時テーブルにアクセスすると以降は効果なし
ファイル
initdb
で700で生成される
主なディレクトリ
base/
- oidを示す数字のディレクトリが作成される
-
格納されるファイル
- テーブル
- インデックス
- TOAST
- Free Space Map
- Visibility Map
global/
- データベース横断的なもの格納
-
pg_database
システムカタログとか\l
とだいたい同じなやつ
pg_wal/
- WALを格納するディレクトリ
pg_xact/
- トランザクションのコミット状態を管理するファイルが格納されている
pg_tblspc/
-
テーブルスペース
base/
以外にもデータベースオブジェクトを格納できる
postgres=# CREATE TABLESPACE mytablespace LOCATION '/var/lib/postgresql/mytablespace';
CREATE TABLESPACE
- 格納先ディレクトリへのsymlinkが格納される
/docker:b612ca6e:/var/lib/postgresql/data $ ls -lA pg_tblspc/
total 0
lrwxrwxrwx 1 postgres postgres 32 2020-01-30 02:00 16387 -> /var/lib/postgresql/mytablespace
主なファイル
PG_VERSION
cat PG_VERSION
12
- メジャーバージョン違いでデータベースクラスタに互換性がないのでそのチェック用
テーブルファイル
ls -lA base/1/
total 7801
-rw------- 1 postgres postgres 8192 2020-01-30 00:02 112
-rw------- 1 postgres postgres 8192 2020-01-30 00:02 113
-rw------- 1 postgres postgres 81920 2020-01-30 00:02 1247
-rw------- 1 postgres postgres 24576 2020-01-30 00:02 1247_fsm
-rw------- 1 postgres postgres 8192 2020-01-30 00:02 1247_vm
...
- 8kB単位のページにより構成
インデックスファイル
- 8kB単位のページにより構成
TOASTファイル
- 長大な行をテーブルに格納するとデータベースディレクトリ配下に生えるディレクトリ
- 公式
- TOAST: The Oversized-Attribute Storage Technique
- 1ページ8kBというサイズ上限をオーバーした属性を格納するための技術
-
2ビットをTOASTに使用するので30ビット = 1GBまで
- textや長さ指定していないvarcharとかは1GB
Free Space Mapファイル
_fsm
Visibility Mapファイル
_vm
WALファイル
- 16MB固定
/docker:b612ca6e:/var/lib/postgresql/data $ ls -lA pg_wal/
total 16388
-rw------- 1 postgres postgres 16777216 2020-01-30 00:52 000000010000000000000001
drwx------ 2 postgres postgres 4096 2020-01-30 00:02 archive_status
max_wal_size
で設定したサイズまで生成される
postgres=# SELECT name,setting,unit,context FROM pg_settings WHERE name='max_wal_size';
name | setting | unit | context
--------------+---------+------+---------
max_wal_size | 1024 | MB | sighup
(1 row)
- 64個まで
postmaster.pid
cat postmaster.pid
1
/var/lib/postgresql/data
1580310138
5432
/var/run/postgresql
*
5432001 163840
ready
- 多重起動とか防止用
- プロセスID
1
- データベースクラスタディレクトリパス
/var/lib/postgresql/data
- サーバ起動時刻(unix timestamp)
1580310138
- ポート番号
5432
- Unixドメインソケットディレクトリパス
/var/run/postgresql
-
listen_address
- TCP接続をリッスンしていなければ空
*
- 共有メモリセグメントID?
5432001 163840