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

#はじめに
にゃーん。

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

#調査方法
* PostgreSQL 13/PostgreSQL 14 beta1を使って、以下の操作を実行。
  * initdb（-Dオプションと-U postgresオプションのみ指定）を実行。
  * 生成されたデータベースクラスタを起動。
  * postgresユーザでpostgresデータベースにログイン。
  * psqlの\aメタコマンドを実行。
  * psqlの\oオプションで出力ファイルを指定。
  * ``SELECT name, setting, unit, category, context, vartype, min_val, max_val FROM pg_settings ORDER BY name;``を実行。
  * 生成されたPostgreSQL 13の結果とPostgreSQL 14-beta1の結果をdiffる。

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

|version|rows|
|:--|--:|
|PostgreSQL 13|329|
|PostgreSQL 14 beta1|344|

結構行数の違いもあるな。

## 差分
PostgreSQL 13とPostgreSQL 14 beta1の設定パラメータ差分のサマリを以下に示す。
今回、結構変更は多いけど、その大半は`category`の変更で`setting`や`context`が変更された設定パラメータはそれほど多くはない。

|パラメータ名|差分種別|差分概要|
|:--|:-:|:--|
|checkpoint_completion_target|変更|デフォルト値が0.5から0.9に変更された|
|client_connection_check_interval|追加||
|cluster_name|変更|categoryが`Process Title`から`Reporting and Logging / Process Title`に変更された|
|compute_query_id|追加||
|debug_discard_caches [^1]|追加||
|default_toast_compression|追加||
|enable_async_append|追加||
|enable_memoize [^2]|追加||
|huge_page_size|追加||
|idle_session_timeout|追加||
|in_hot_standby|追加||
|lc_collate|変更|`category`が`Client Connection Defaults / Locale and Formatting`から`Preset Options`に変更された|
|lc_ctype|変更|`category`が`Client Connection Defaults / Locale and　Formatting`から`Preset Options`に変更された|
|log_recovery_conflict_waits|追加||
|min_dynamic_shared_memory|追加||
|operator_precedence_warning|削除||
|password_encryption|変更|デフォルト値が`md5`から`scram-sha-256`に変更された<br>また``on``や``1``を値域から外した|
|recovery_init_sync_method [^3]|追加||
|remove_temp_files_after_crash [^4] |追加||
|restore_command|変更|`context`が`postmaster`から`sighup`に変更された|
|server_encoding|変更|`category`が`Client Connection Defaults / Locale and Formatting`から`Preset Options`に変更された|
|ssl_crl_dir|追加||
|synchronous_standby_names|変更|`category`が`Replication / Master Server`から`Replication / Primary Server`に変更された|
|tcp_keepalives_count|変更|`category`が`Client Connection Defaults / Other Defaults`から`Connections and Authentication / Connection Settings`に変更された(*1)|
|tcp_keepalives_idle|変更|(*1)と同じ|
|tcp_keepalives_interval|変更|(*1)と同じ|
|tcp_user_timeout|変更|(*1)と同じ|
|track_activity_query_size|変更|`category`が`Resource Usage`から`Statistics / Query and Index Statistics Collector`に変更された|
|track_commit_timestamp|変更|`category`が`Replication`から`Replication / Sending Servers`に変更された|`category`が`Resource Usage`から`Statistics / Query and Index Statistics Collector`に変更された|
|track_wal_io_timing|追加||
|update_process_title|変更|`category`が`Process Title`から`Reporting and Logging / Process Title`に変更された|
|vacuum_cleanup_index_scale_factor|削除||
|vacuum_cost_page_miss|変更|デフォルト値が10から2に変更された|
|vacuum_defer_cleanup_age|変更|`category`が`Replication / Master Server`から`Replication / Primary Server`に変更された|
|vacuum_failsafe_age|追加||
|vacuum_multixact_failsafe_age|追加|

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

## client_connection_check_interval
長時間実行されるクエリのクライアントが切断されたときに、このパラメータで指定された数値(ms)を超えた場合にクエリを中断する新機能のパラメータっぽい。デフォルト値は0で、0の場合にはこの機能は無効になる。
また、この機能はOSによって有効/無効なものがあるもよう。Linuxは有効と記載があるが、Winodwsはどうなんだろう・・・？

## compute_query_id
サーバー変数 compute_query_id が有効になっている場合、クエリ ID を pg_stat_activity、EXPLAIN VERBOSE、csvlog、およびオプションで log_line_prefix に表示するというものらしい。
型はenumで、off/on/autoの3種類。デフォルト値はauto。autoを設定するとpg_stat_statementsで使われるようになるようだけど、このへんは動作確認してみないと今ひとつ良くわからないな。

## debug_discard_caches
キャッシュ（ここでいうキャッシュというのはなんだろう？共有バッファのことか？）の上書きを制御するパラメータ。
型はintegerで、デフォルト値は0。
どんな値を設定すると何が起きるのか、リリースノートだけを見てもわからないので、[20.17. Developer Options](https://www.postgresql.org/docs/14/runtime-config-developer.html)を見る必要がある。
1を設定すると、システムカタログのキャッシュが実質的に無効になり、サーバーの動作が非常に遅くなるらしい。2以上にするとそれを「再帰的に実行する」とあるが、正直あまり意味はわからない。
まあ開発者向けのオプションなので、通常の運用で使うものではない。
なお``context``は``superuser``なので、サーバ実行中に挙動も変更できるのかな。

## default_toast_compression
PostgreSQLのTEXT型などは[TOAST](https://www.postgresql.org/docs/14/storage-toast.html)対象となった場合、圧縮と外部化を行うが、その圧縮アルゴリズムとしてて従来のpglzの他に、lz4が選択できるようになった。
lz4をちらっと調べると圧縮/展開の高速化に特化した方式らしい（圧縮率は悪くなる）。→[Wikipedia LZ4](https://ja.wikipedia.org/wiki/LZ4)
従来のpglzを用いたTOAST列の復元時（検索時とか）の性能を改善したいときに、効果があるかもしれない。
型はenum。値域はpglz, lz4の2つ。デフォルトはpglz。
なお、lz4を指定する場合には、configure時に`--with-lz4`を指定する必要がある（beta版のRPMがこのオプション付きでビルドされているのかは未確認）。
これは測定して効果を試したい機能だ。

## enable_async_append
プランナによる非同期追加プランタイプの使用を有効または無効にするパラメータ。デフォルトはon。
リリースノートの"Allow a query referencing multiple foreign tables to perform foreign table scans in parallel"の内容、Commitfestでいうと、[Asynchronous Append on postgres_fdw nodes.](https://commitfest.postgresql.org/32/2491/) の内容だと思う。

## enable_memoize
ネストされたループ結合の内側からの結果をキャッシュするexecuteメソッドを追加。これは、インナーサイドでチェックされる行の割合が少ない場合に便利で、enable_memoize で制御される、とのこと。デフォルトはon。
リリースノートの

> Add executor method to cache results from the inner-side of nested loop joins (David Rowley)
This is useful if only a small percentage of rows is checked on the inner side and is controlled by enable_memoize.

に該当する項目。

## huge_page_size
huge_pages で有効になっている場合の huge pageのサイズを制御する。
デフォルトは0。 0に設定すると、システムのデフォルトのhuge pageサイズが使用されるとのこと。

## idle_session_timeout
idle状態のセッションについてもタイムアウト機能が入ったもよう。デフォルトは0（無効）。
この設定を有効にしておくことで、例えばpsqlでログインしっぱなしの端末の接続を切断する・・・とかに使えるんだろう。
（PostgreSQL 9.6ではidle in transaction状態セッションのタイムアウト機能は入ったが、単なるidle状態のセッションのタイムアウト機能はなかった）

## in_hot_standby
サーバーが現在ホットスタンバイモードかどうかを報告する。
これがonの場合、すべてのトランザクションは強制的に読み取り専用になる。
セッション内では、これはサーバーがプライマリに昇格された場合にのみ変更できる。
``context``は``Preset Option``なので運用者が変更等できるわけではないけど。

## log_recovery_conflict_waits
起動プロセスがリカバリの競合のために Deadlock_timeout よりも長く待機したときに、ログを生成するかどうかを制御する。リカバリの競合によってリカバリ処理が WAL を適用できないかどうかを判断するのに役立つものらしい・・・。 
``context``は``sighup``。デフォルト値はoff。

## recovery_init_sync_method
クラッシュリカバリを行うときの同期メソッドを指定できるようになったらしい。
型はenum。値域は``fsync``と``syncfs``（の2つのかな？）・デフォルトは``fsync``。
``fsync``を指定した場合、クラッシュ リカバリが開始される前に、データ ディレクトリ内のすべてのファイルを再帰的に開いて同期する。
Linux上であれば、代わりに``syncfs``を指定できる。この場合、OSに、データ ディレクトリ、WAL ファイル、および各テーブルスペースを含むファイルシステム全体を同期する依頼ができる。で、超早いらしい。
（細かい注意点は[recovery_init_sync_method](https://www.postgresql.org/docs/14/runtime-config-error-handling.html#GUC-RECOVERY-INIT-SYNC-METHOD)参照）

## remove_temp_files_after_crash
バックエンドクラッシュ後に一時ファイルの削除をするかどうかを制御する。
デフォルトはon。onの場合、バックエンドのクラッシュ後に一時ファイルを自動的に削除する。
offにすると、クラッシュ時も一時ファイルは保持される。開発者のデバッグ用の機能で、通常の運用でこれをoffる必要はなさそう。

## track_wal_io_timing
WAL I/O 呼び出しのタイミングを有効にします。
このパラメーターは、OSに現在時刻を繰り返し照会するため、デフォルトではおoffにしている。
onにすると、一部のプラットフォームで大きなオーバーヘッドが発生する可能性がある。I/O timing情報は pg_stat_wal に表示される。
``context``は``superuser``。

## vacuum_failsafe_age/vacuum_multixact_failsafe_age
テーブルが xid または multixact 周回に近い場合、バキューム操作を積極的に実行させるためのパラメータっぽい。

### vacuum_failsafe_age
vacuum_failsafe_ageのデフォルト値は1600000000（16億）。
この閾値を超えるとコストベースのバキューム遅延も行わず全力でバキュームをするように読める。
また、VACUUM処理の中で[autovacuum_freeze_max_age](https://www.postgresql.org/docs/14/runtime-config-autovacuum.html#GUC-AUTOVACUUM-FREEZE-MAX-AGE) の 105% 以上に調整するとも書いてある。

### vacuum_multixact_failsafe_age
vacuum_failsafe_ageとだいたい同じ。デフォルト値は1600000000（16億）。
また、VACUUM処理の中で[autovacuum_multixact_freeze_max_age](https://www.postgresql.org/docs/14/runtime-config-autovacuum.html#GUC-AUTOVACUUM-MULTIXACT-FREEZE-MAX-AGE) の 105% 以上に調整するとも書いてある。

# 削除されたパラーメタ
しれっと2つパラメータが削除されている。
## operator_precedence_warning
このパラメータは「PostgreSQL 9.5 の変更に関する警告」のためのものだったけど、PostgreSQL 9.5がEOLになったのでPostgreSQL 14からはパラメータ自体削除したっぽい。
 
## vacuum_cleanup_index_scale_factor
実はこのパラメータ、PostgreSQL 13 Documentにはないが、PostgreSQL 13には実装されていたパラメータっぽい。
（PostgreSQL 12 Documentには存在している）
で、PostgreSQL 14でしれっと実装も削除されたように見える・・・
なお、リリースノートへの記述はない。

# 変更されたパラメータ
今回のバージョンでは`category`の変更が結構多いが、それ以外に設定値が変わったものもいくつかある。それらをピックアップする。
## checkpoint_completion_target
デフォルト値が0.5から0.9に変わった、ということで何もチューニングしなければ、今までのバージョンよりもチェックポイント時の急激なI/O増が抑えられる（代わりにチェックポイント自体の時間は伸びる）という挙動になるんだろうか。

## log_line_prefix
これは自分の調査方法だと差分が見つけられなかったもの。コメントを受けて追記した。
PostgreSQL 14では、以下の記法も追加された。

|記法|展開される内容|
|:--|:--|
|%P |このプロセスがパラレルクエリワーカーの場合、パラレルグループリーダーのプロセス ID   |
|%Q |現在のクエリのクエリ識別子。compute_query_idパラメータが有効になっているか、クエリ識別子を計算するサードパーティモジュールが有効でないと、このフィールドはゼロになる。   |

## restore_command
PostgreSQL 12からrecovery.confがpotsgresql.confに統合されたことで、restore_commandも追加されたのだが、これがPostgreSQL 14では`sighup`という扱いになった。
これって、リカバリ中にreloadすることでアーカイブファイルの処理を変更するようなことができるってことなんだろうか。例えば、アーカイブファイルを複製しておいて、アーカイブファイル破損したときに、別の場所からリストアさせるためのリロードするとか・・・ができるんだろうか。

## password_encryption
デフォルト値が`md5`から`scram-sha-256`についに変更になった。
もしかすると近い将来、認証方式として`md5`指定は廃止されるのかな。
あと、PostgreSQL 13までは、``on``や``1``の設定値を許容（``md5``と見なされる）していたが、PostgreSQL 14からは``on``や``1``がenumの値域から外れた（HINTメッセージは同じだけど。そういうとこだぞ＞PostgreSQL）。

PostgreSQL 13まで

```sql
postgres=# SHOW password_encryption ;
 password_encryption
---------------------
 md5
(1 row)

postgres=# SET password_encryption = 1;
SET
postgres=# SET password_encryption = 0;
ERROR:  invalid value for parameter "password_encryption": "0"
HINT:  Available values: md5, scram-sha-256.
postgres=# SET password_encryption = on;
SET
postgres=# SET password_encryption = off;
ERROR:  invalid value for parameter "password_encryption": "off"
HINT:  Available values: md5, scram-sha-256.
postgres=#
```
PostgreSQL 14

```sql
postgres=# SHOW password_encryption ;
 password_encryption
---------------------
 scram-sha-256
(1 row)

postgres=# SET password_encryption = 1;
ERROR:  invalid value for parameter "password_encryption": "1"
HINT:  Available values: md5, scram-sha-256.
postgres=#
```

## unix_socket_directories
これも自分の調査方法では見つけられず、コメントを受けて追記したもの。

> A value that starts with @ specifies that a Unix-domain socket in the abstract namespace should be created (currently supported on Linux and Windows). 

`@`で始まる場合は「抽象名前空間」にUnixドメインソケットを作成するということみたいだけど、そもそも「抽象名前空間」って何？という状態なので、そこから調べないとな・・・

## vacuum_cost_page_miss
このパラメータは、

> ディスクから読み込まれなければならないバッファにvacuumを掛ける予測コスト

（PostgreSQL 12文書の抜粋）なんだけど、そのデフォルト値が10から2に変更された。変更になった理由はリリースノート曰く「新しいデフォルト値は、現在のハードウェア機能をより適切に反映している」ということらしい。 


# おわりに
PostgreSQL 14では想定以上に多くの設定パラメータの変更があった。その分、新機能もいろいろ増えているということなので楽しみだ。
今回の記事は机上調査でしかないので、今後、各機能を実際に動かしてみてどういう新機能が追加されたのかを確認していきたい。

[^1]: beta1のときは debug_invalidate_system_caches_always というパラメータ名であった。
[^2]: beta1のときには enable_resultcache というパラメータ名であった。
[^3]: beta1のときのcontextは postmaster であったが、beta3時点では sighup になっていた。
[^4]: beta1のときのcategoryは Error Handling であったが、beta3時点では Developer Options になっていた。