PostgreSQL 18がやってくる(1) 設定パラメータの差分

# はじめに
にゃーん。
いつものように、PostgreSQL新バージョンの差分先行調査の時期になりました。
ということで、今回はPostgreSQL 17とPostgreSQL 18devの設定パラメータの差分を調べてみる。

# 調査方法
* PostgreSQL 17/PostgreSQL 18dev(commitid 2a0cd38da5ccf70461c51a489ee7d25fcd3f26be)を使って、以下の操作を実行。
  * initdb（-Dオプションと-U postgresオプションのみ指定）を実行。
  * 生成されたデータベースクラスタを起動。
  * postgresユーザでpostgresデータベースにログイン。
  * psqlの\aメタコマンドを実行。
  * psqlの\oオプションで出力ファイルを指定。
  * ``SELECT name, setting, unit, category, context, vartype, min_val, max_val, enumvals FROM pg_settings ORDER BY name;``を実行。[^1]
* 生成されたPostgreSQL 16の結果とPostgreSQL 17develの結果をdiffる。
* パラメータの説明は調査時点(205-03-24)のPostgreSQL Document(devel)に記載された内容を元にしている。

# 調査結果
## 行数
SELECT文の行数(rows)

|version|rows|
|:--|--:|
|PostgreSQL 17|377|
|PostgreSQL 18dev|397|

17と比較すると20パラメータ増えている。


## 差分概要
PostgreSQL 17とPostgreSQL 18devの設定パラメータ差分のサマリを以下に示す。
今回も追加/変更されたパラメータは結構多い。

|パラメータ名|種別|差分概要|
|:--|:-:|:--|
|autovacuum* (13個)  |変更   |categoryがAutovacuum→Automatic Vacuuming   |
|autovacuum_worker_slots   |追加   |   |
|backend_flush_after   |変更   |categoryがResource Usage / Asynchronous Behavior→Resource Usage / I/O   |
|data_checksums   |変更   |設定値がoff→on   |
|effective_io_concurrency   |変更   |設定値が1→16   |
|enable_distinct_reordering   |追加   |プランナメソッド制御パラメータの追加   |
|enable_self_join_elimination   |追加   |プランナメソッド制御パラメータの追加   |
|extension_control_path   |追加   |   |
|idle_replication_slot_timeout   |追加   |   |
|io_combine_limit   |変更|categoryがResource Usage / Asynchronous Behavior→Resource Usage / I/O<br>最大値が32→128   |   |
|io_max_combine_limit   |追加   |   |
|io_max_concurrency   |追加   |   |
|io_method   |追加   |   |
|io_workers   |追加   |   |
|log_connections   |変更   |設定方法に大きな変化あり。   |
|log_lock_failure   |追加   |   |
|log_rotation_size   |変更   |最大値が2097151→2147483647   |
|maintenance_io_concurrency   |変更   |categoryがResource Usage / Asynchronous Behavior→Resource Usage / I/O<br>設定値が10→16  |
|max_active_replication_origins   |追加   |  |
|max_parallel_maintenance_workers   |変更   |categoryがResource Usage / Asynchronous Behavior→Resource Usage / Worker Processes   |
|max_parallel_workers   |変更   |categoryがResource Usage / Asynchronous Behavior→Resource Usage / Worker Processes   |
|max_parallel_workers_per_gather   |変更   |categoryがResource Usage / Asynchronous Behavior→Resource Usage / Worker Processes   |
|max_worker_processes   |変更   |categoryがResource Usage / Asynchronous Behavior→Resource Usage / Worker Processes   |
|md5_password_warnings   |追加   |   |
|num_os_semaphores   |追加   |   |
|oauth_validator_libraries   |追加   |   |
|parallel_leader_participation   |変更   |categoryがResource Usage / Asynchronous Behavior→Resource Usage / Worker Processes   |
|query_id_squash_values   |追加   |   |
|shared_memory_size   |変更   |設定値が143→150   |
|shared_memory_size_in_huge_pages   |変更   |設定値が72→75   |
|ssl_ecdh_curve   |削除   |ssl_groupsにリネーム？   |
|ssl_groups   |追加   |   |
|ssl_tls13_ciphers   |追加   |   |
|track_cost_delay_timing   |追加   |   |
|vacuum_* (11個)   |変更   |categoryがResource Usage / Cost-Based Vacuum Delay→Vacuuming / Cost-Based Vacuum Delay   |
|vacuum_truncate   |追加   |   |


# 追加されたパラメータ
PostgreSQL 18では結構多くのパラメータの追加がある。

## autovacuum_worker_slots

|項目|説明|
|:--|:--|
|カテゴリ|Vacuuming / Automatic Vacuuming|
|context|postmaster|
|データ型|integer|
|説明|autovacuum ワーカープロセス用に確保するバックエンドスロットの数を指定する。autovacuum_max_workersも一緒に調整が必要。|
|デフォルト値|16|

【メモ】

autovacuum_worker_slots数よりautovacuum_max_workers数が小さい場合は、どうなるんだろう？

## enable_distinct_reordering

|項目|説明|
|:--|:--|
|カテゴリ|Query Tuning / Planner Method Configuration|
|context|user|
|データ型|bool|
|説明|入力パスのパスキーと一致するようにDISTINCTキーを並べ替える問い合わせプランナの機能を有効もしくは無効にする。|
|デフォルト値|on|

【メモ】
[Reordering DISTINCT keys to match input path's pathkeys](https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=a8ccf4e93a7eeaae66007bbf78cf9183ceb1b371)をチラ見したけど、DISTINCTとORDER BYを含むクエリで状況によってはより良いプランを生成してくれるのかな。


## enable_self_join_elimination

|項目|説明|
|:--|:--|
|カテゴリ|Query Tuning / Planner Method Configuration|
|context|user|
|データ型|bool|
|説明|問い合わせツリーを分析し、自己結合を意味的に等価な単一スキャンに置き換える問い合わせプランナの最適化を有効もしくは無効にする。|
|デフォルト値|on|

【メモ】
[Remove self join on a unique column](https://commitfest.postgresql.org/patch/5043/)関連かな？
MLの議論は追ってない・・・。

## extension_control_path

|項目|説明|
|:--|:--|
|カテゴリ|Client Connection Defaults / Other Defaults|
|context|superuser|
|データ型|string|
|説明|エクステンションコントロールファイル(name.control)を検索するパス。<br>extension_control_pathの値は、コロン（Windowsではセミコロン）で区切られた絶対ディレクトリパスのリストでなければならない。<br>リスト要素が特殊文字列``$system``で始まる場合、コンパイル済みのPostgreSQL拡張ディレクトリが```$system``に代入される。|
|デフォルト値|$system|

【メモ】
Commitfest [Add extension_destdir GUC](https://commitfest.postgresql.org/patch/4913/)

どういう用途でデフォルト（``$system``）以外を使うのか？
MLをチラ見した感じだとDocker環境でPostgreSQLを動かす時に関連しそうなのかな。

## idle_replication_slot_timeout

|項目|説明|
|:--|:--|
|カテゴリ|Replication / Sending Servers|
|context|sighup|
|データ型|integer|
|値域|0～35791394|
|説明|この持続時間以上アイドル状態のレプリケーション・スロットを無効にする。この値が単位なしで指定された場合、分として扱う。値0（デフォルト）はアイドルタイムアウト無効化機構を無効にする。|
|デフォルト値|0|

【メモ】
レプリケーション・スロットが無効になるって、削除されるのとは別？
無効化されたあと、そのスロットを有効化するSQLコマンドやSQL関数ってあったっけ？


## io_max_combine_limit

|項目|説明|
|:--|:--|
|カテゴリ|Resource Usage / I/O|
|context|postmaster|
|データ型|integer|
|値域|1～128|
|説明|I/Oを結合する操作における最大のI/Oサイズを制御し、ユーザ設定可能なパラメータio_combine_limitを自動的に制限する。 |
|デフォルト値|16(128kB)|

【メモ】
io_combine_limit自体、きちんと理解していない・・・。
単位なしのときはページ(8kB)数になるのかな。

## io_max_concurrency

|項目|説明|
|:--|:--|
|カテゴリ|Resource Usage / I/O|
|context|postmaster|
|データ型|integer|
|値域|-1～1024|
|説明| 1つのプロセスが同時に実行できるI/O操作の最大数を制御する。<br>デフォルト設定の-1では、shared_buffersとプロセスの最大数（max_connections、autovacuum_worker_slots、max_worker_processes、max_wal_senders）に基づく数が選択されるが、64は超えない。|
|デフォルト値|-1|

【メモ】
initdb直後の状態でこのパラメータの値を確認すると-1ではなく64になっている。
ドキュメント記述の誤りなのか、環境によって64が設定されるのかは不明。
0が設定された場合の挙動はどうなる？
I/O操作が一切できなくなるのだろうか・・・？

## io_method

|項目|説明|
|:--|:--|
|カテゴリ|Resource Usage / I/O|
|context|postmaster|
|データ型|enum|
|値域|sync, io_uring, worker|
|説明|非同期I/Oの実行方法を選択する。<br>worker：ワーカープロセスを使って非同期I/Oを実行する<br>io_uring：io_uring を使って非同期 I/O を実行する。``--with-liburing -Dliburing`` を使ったビルドが必要<br>sync：非同期I/Oを同期的に実行する|
|デフォルト値|worker|

【メモ】
io_uring 自体があまり良くわかっていない。どういうときのユースケースとして有効なのか？
``--with-liburing``を指定しないでビルドすると、enumとしても``io_uring``は現れない。

## io_workers

|項目|説明|
|:--|:--|
|カテゴリ|Resource Usage / I/O|
|context|sighup|
|データ型|integer|
|値域|1～32|
|説明|使用するI/Oワーカー・プロセスの数を選択する。<br>io_methodがworkerに設定されている場合のみ有効|
|デフォルト値|3|

【メモ】
io_methodのデフォルト値がworkerになっているので、非同期I/Oを活用するためには、これもきちんとチューニングしないといけないのかな。
（自宅環境のようなしょぼい環境だとあまりありがたみはなさそうだけど・・・）

## log_lock_failure

|項目|説明|
|:--|:--|
|カテゴリ|Reporting and Logging / What to Log|
|context|superuser|
|データ型|bool
|説明|ロックの獲得に失敗したときに詳細なログ・メッセージを生成するかどうかを制御する。<br>現状、NOWAITによるロック失敗のみがサポートされいる。|
|デフォルト値|off|

【メモ】
NOWAITオプションつきのLOCKを発行するときくらいしか、メッセージ発行契機がないから、18の時点だとデフォルト値はoffにしているのかな。

## max_active_replication_origins

|項目|説明|
|:--|:--|
|カテゴリ|Replication / Subscribers|
|context|postmaster|
|データ型|integer|
|値域|0～262143|
|説明|同時に追跡できるレプリケーション起点の数を指定する。少なくともサブスクライバに追加されるサブスクリプション数と、テーブル同期のための予備数を設定しなければいけない。|
|デフォルト値|10|

【メモ】
大量のテーブルが存在する環境で、論理レプリケーションをテーブル単位で細かく定義する場合には、このパラメータの調整も必要になるのかな。


## md5_password_warnings

|項目|説明|
|:--|:--|
|カテゴリ|Connections and Authentication / Authentication|
|context|user|
|データ型|bool|
|説明|（現状ドキュメント未）|
|デフォルト値|on|

【メモ】
なんとなくパラメータ名から、pg_hba.confのmethodにmd5を指定してreloadしたときに、警告を出力するような感じがするが実際はどうなんだろ。動かして確認するほうが早いかしらん。

## num_os_semaphores

|項目|説明|
|:--|:--|
|カテゴリ|Preset Options|
|context|internal|
|データ型|integer|
|値域|0～2147483647|
|説明|max_connections, autovacuum_max_workers, max_wal_sendersmax_worker_processesなどに基づいて、サーバに必要なセマフォ数を報告する。|
|デフォルト値|174|

【メモ】
このデフォルト値は環境依存なのかな。
Preset Optionsなので、DBAが何かチューニングしたりするパラメータではなさそうだけど。

## query_id_squash_values

|項目|説明|
|:--|:--|
|カテゴリ|Statistics / Monitoring|
|context|user|
|データ型|bool|
|説明|(現時点ではマニュアル記述なし)<br>query_idを計算する際に、リスト内の定数をマージする。|
|デフォルト値|off|

【メモ】
pg_stat_statements等でWHERE句のIN等のリストの定数をもつ複数のクエリをマージする感じなんだろうか？

## oauth_validator_libraries

|項目|説明|
|:--|:--|
|カテゴリ|Connections and Authentication / Authentication|
|context|sighup|
|データ型|string|
|説明|OAuth 接続トークンの検証に使用するライブラリ。<br>バリデータライブラリをひとつだけ指定した場合は、 そのライブラリがデフォルトで OAuth 接続に使われる。<br>空文字列 (デフォルト) を設定すると、OAuth 接続は拒否される。|
|デフォルト値|NULL|

【メモ】
OAuth接続自体、良くわかっていない・・・勉強が足りん。

## ssl_groups

|項目|説明|
|:--|:--|
|カテゴリ|Connections and Authentication / SSL|
|context|sighup|
|データ型|string|
|説明| ECDH鍵交換で使用するカーブ名を指定する。<br>デフォルトは X25519:prime256v1 。|
|デフォルト値|none|

【メモ】
ECDH鍵自体が良くわかっていない・・・
自分の環境の設定値が``none``になっているのは、configureオプションでこのパラメータを有効にするために必要な指定がないから？

## ssl_tls13_ciphers

|項目|説明|
|:--|:--|
|カテゴリ|Connections and Authentication / SSL|
|context|sighup|
|データ型|string|
|説明| TLSバージョン1.3を使用する接続で許可される暗号化スイートのリストを指定する。コロンで区切ったリストを使用することで、複数の暗号化スイートを指定できる。<br>空白のままにしておくと、OpenSSLのデフォルトの暗号スイートが使用される。|
|デフォルト値|空値|

【メモ】
「暗号化スイート」とはなにか。
TLSなんもわからん・・・。

## track_cost_delay_timing

|項目|説明|
|:--|:--|
|カテゴリ|Statistics / Cumulative Query and Index Statistics|
|context|superuser|
|データ型|bool|
|説明|コストベースのバキューム遅延のタイミング情報を有効にする。<br>このパラメータはオペレーティングシステムに繰り返し現在の時刻を問い合わせるため、デフォルトではオフになっている。<br>この情報は、pg_stat_progress_vacuum、pg_stat_progress_analyze、VERBOSEオプション使用時のVACUUMの出力、log_autovacuum_min_durationがで使われる。|
|デフォルト値|off|

【メモ】
通常運用時にはoffにしておいて、なんか思ったような契機でautovacuumが実行されないような問題があったときに、一時的にonにして解析するのに使ったりするのかな・・・？

## vacuum_truncate

|項目|説明|
|:--|:--|
|カテゴリ|Vacuuming / Default Behavior|
|context|user|
|データ型|bool|
|説明|テーブルの最後にある空のページをバキュームで切り捨てるかどうかを設定する。onの場合、VACUUMとautovacuumが切り捨てを行い、切り捨てられたページのディスク領域がOSに返される。|
|デフォルト値|on|

【メモ】
PostgreSQL 17までの動作はonになる。
これをoffにすると、末尾の切り捨て処理をスキップするのでVacuum自体の処理時間が短くなる（代わりに使用ディスク領域は減らない）ということなんだろうか。

大量レコードが存在するテーブルを全件DELETE→手動VACUUM実行で比較すると動きがわかりやすそう。

# 削除されたパラメータ

## ssl_ecdh_curve
この名前のパラメータが削除されて、ssl_groupsになったのかも。

# 変更されたパラメータ
## カテゴリ名の変更
PostgreSQL 18devではカテゴリの見直しも行っている。
以下に、PostgreSQL 17→PostgreSQL 18devで変更されたパラメータのカテゴリ名を示す。

|PostgreSQL 17|PostgreSQL 18dev|種別|備考|
|:--|:--|:--|:--|
|Resource Usage / Cost-based Vacuum Delay  |Vacuuming / Cost-based Vacuum Delay |移動|Vacuumingの下に移動した。 |
|Resource Usage/ Asynchronous Behavior |-|追加 |I/O と Worker Processes に分離 |
|- |Resource Usage / I/O |追加 | |
|- |Resource Usage / Worker Processes | |
|Automatic Vacuuming|Vacuuming|変更|Automatic VacuumingとVacuumingを統合|
|- |Vacuuming / Automatic Vacuuming|追加 |17のAutomatic Vacuumingがここに移動したっぽい|
|- |Vacuuming / Default Behavior|追加|18devではvacuum_truncateのみ|
|- |Vacuuming / Freezing|追加 |Client Connection Defaults / Statement Behavior等にあったVacuum freeze関連のパラメータをここに移動したようだ|

カテゴリ名のみ変更されたパラメータについては、以降では説明省略。

## data_checksums

|変更列|PostgreSQL 17|PostgreSQL 18dev|
|:--|:--|:--|
|setting|off|on|

【メモ】
今回、``initdb``時に明示的にチェックサムに関するオプションを指定しなかった。
17では明示的に-data-checksums(-k)を指定しないとチェックサムは無効(off)になるが、**18devではデフォルトでチェックサムが有効(on)になるようだ。**

## effective_io_concurrency

|変更列|変更前|変更後|
|:--|:--|:--|
|setting|1|16|

【メモ】
このパラメータは、PostgreSQLが同時に実行できると想定するディスク（ストレージ）I/O操作の数を設定するもの。
PostgreSQL 17まではデフォルト値は1だった。また、PostgreSQL文書上、この設定はビットマップヒープスキャンにのみ影響する、と記載されている。
PostgreSQL 18devでは、プリフェッチアドバイスをサポートしているシステムでは16、そうでない場合は0が設定される、と読める。
IOPが非常に高いシステムでは、これをきちんとチューニングするとI/Oまわりの性能に影響するのだと想像。

## io_combine_limit

|変更列|変更前|変更後|
|:--|:--|:--|
|max|32|128|

【メモ】
最大値が4倍になっている。
PostgreSQL 18devの文書を見ると「通常Unixでは1MB、Windowsでは128kBである。デフォルトは128kBである。」という記述がある。このパラメータのunitは「8kB」なので、おそらくconfigure時にLinuxなので128 * 8kB = 1Mになるように、最大値として128が設定されているのではと推測している。

## log_connections

|変更列|変更前|変更後|
|:--|:--|:--|
|setting|off|空文字|
|vartype|bool|string|

【メモ】
**18devではlog_connectionの内容に大きな変更が入った。**
17まではbool型(on/off)であったが、18devではstring型になっている（！）
18devでは以下の値をカンマ区切りで（つまり複数）指定可能。

|設定文字列|意味|
|:--|:--|
|空文字 |デフォルト値<br>接続ログそ全て無効にする。|
|receipt |接続の受信をログに記録する。 |
|authentication |認証方式がユーザを識別するために使用した元のIDをログに記録する。<br>ほとんどの場合、ID文字列はPostgreSQLのユーザ名と一致するが、サードパーティの認証方法の中には、サーバが保存する前に元のユーザ識別子を変更してしまうものもある。<br>認証に失敗した場合は、この設定の値に関係なく常にログに記録される。|
|authorization |認証が正常に完了したことをログに記録する。この時点で接続は確立されているが、バックエンドはまだ完全にセットアップされていない。<br>ログメッセージには、認証されたユーザ名、データベース名、アプリケーション名 (もしあれば) が含まれる。|
|setup_durations |接続が最初の問い合わせを実行する準備ができた時点で、接続の確立とバックエンドの設定に費やされた時間をログに記録する。<br>このログメッセージには、postmaster が接続を受け付けてからクエリの準備が完了するまでの、セットアップにかかった時間が含まれる。<br>また、新しいバックエンドをフォークするのにかかった時間と、ユーザを認証するのにかかった時間も含まれる。|
|all |すべてのオプションを指定するのと同等の便利なエイリアス。他のオプションのリストで all を指定すると、すべての接続フェーズがログに記録される。 |

従来と同じ接続ログ指定を期待する場合には、``all``を指定すれば良いのかな。
これは実際に動かして、どんなログが出るのか検証したほうが良さそうだ。

なお、接続切断ログは従来どおり、``log_disconnections``で制御する。こちらはbool型のまま。

## log_rotation_size

|変更列|変更前|変更後|
|:--|:--|:--|
|max_val|2097151|2147483647|

【メモ】
[pgsql: Remove obsolete restriction on the range of log_rotation_size.](https://www.postgresql.org/message-id/E1tdwp5-004g1b-Nt@gemulon.postgresql.org)によると、
> syslogger.cが最初に書かれたとき、すべてのプラットフォームが64ビットftelloを持っていると仮定はしてなかった。しかし、v13からそれを想定している（コミット799d22461参照）ので、syslogger.cでそれを使い、log_rotation_sizeをINT_MAXキロバイトまでの範囲にすることした。

ということらしい・・・。

## maintenance_io_concurrency

|変更列|変更前|変更後|
|:--|:--|:--|
|setting|10|16|

【メモ】
10から16に増やした議論は[Increase default maintenance_io_concurrency to 16](https://www.postgresql.org/message-id/E1tuWgZ-0035xZ-0x@gemulon.postgresql.org)ぽい。
別のコミットで、effective_io_concurrencyを16に増やしたので、それに合わせてmaintenance_io_concurrencyも増やした、という経緯に読める。

## shared_memory_size

|変更列|変更前|変更後|
|:--|:--|:--|
|setting|143|150|

【メモ】
この値が変更された理由がわからない・・・。（コミットログを検索したけどそれっぽい情報は見つけられなかった）
Preset Optionsなので、あまり気にするパラメータではないのかもしれないけど。 

## shared_memory_size_in_huge_pages

|変更列|変更前|変更後|
|:--|:--|:--|
|setting|72|75|

【メモ】
この値が変更された理由がわからない・・・。（コミットログを検索したけどそれっぽい情報は見つけられなかった）
Preset Optionsなので、あまり気にするパラメータではないのかもしれないけど。 

# おわりに
PostgreSQL 18でも多くの設定パラメータの変更があるようだ。
特にlog_connectionsは設定方式が大きく変わりそうなので要注意。
まだ、一部のパラメータはPostgreSQL文書への記載がないので、調査としては完全ではないけど、PostgreSQL 18でも、かなりパラメータの変更があるのはわかってきた。

今回の記事は机上調査でしかないので、今後、各機能を実際に動かしてみてどういう新機能が追加されたのかを確認していきたい（特にlog_connections設定のあたりとか）。
また、この調査結果はあくまでも3/29時点のものなので、今後開発が進んでbeta以降で変更される可能性も大いにありうる。