PostgreSQL 14がやってくる(2) - システムカタログの差分

# はじめに
にゃーん

今回は、PostgreSQL 13とPostgreSQL 14のシステムカタログの差分を調べてみる。
これもまだβ1版なので、今後変わっていく可能性が大きいけど、現時点の版で調査をしてみた。

## 調査方法
PostgreSQL 13までの調査方法（[PostgreSQL 13がやってくる！(2) - システムカタログの差分を調べてみる](https://qiita.com/nuko_yokohama/items/a60459552e60d0467d40)参照）を変更した。
PostgreSQL 13とPostgreSQL 14それぞれで以下の手順を実施。

* psqlでログイン
* `\o` *ファイル名* メタコマンドで出力先ファイルを指定
* `a` メタコマンドで整形用の空白が入らないようにする。
* 以下のSELECT文を実行してpsqlを終了する。

```sql
SELECT c.relname, attname, atttypid
FROM pg_class c JOIN pg_attribute a ON (a.attrelid = c.oid) JOIN pg_namespace ns ON (c.relnamespace = ns.oid)
WHERE ns.nspname = 'pg_catalog' AND c.relkind = 'r'
ORDER BY c.relname, a.attname
;
```
ソートはリレーション名と属性名にする。（あえてリレーション内の属性の並び番号ではソートしない）

* psqlを終了する。
* PostgreQSL 13の検索結果ファイルと、PostgreSQL 14の検索結果ファイルをdiffる。

システムビューについても同様に差分を取得する（SELECT文の `c.relkind = 'r'`の箇所を`v`に変更する）。

# テーブル/ビュー単位での変更まとめ
システムテーブルのテーブル単位での新規追加はないが、システムビューはいくつか新規追加されたものがある。

## システムテーブル
新規にテーブル単位で追加されたものはなさそう。

|テーブル名|変更種別|その他修正|
|:--|:-:|:--|
|pg_attribute |変更|attcompression 列の追加 |
|pg_inherits  |変更|inhdetachpending 列の追加 |
|pg_proc      |変更|prosqlbody 列の追加 |
|pg_range     |変更|rngmultitypid 列の追加 |
|pg_statistic_ext |変更|stxexprs 列の追加 |
|pg_statistic_ext_data |変更|stxdexpr 列の追加 |
|pg_subscription |変更|subbinary 列の追加<br>substream 列の追加|
|pg_type |変更|typsubscript 列の追加|

## システムビュー
こっちのほうが変更が多い。追加されたビューもある。
`pg_stat_database`への列追加が多い。

|ビュー名|変更種別|その他修正|
|:--|:-:|:--|
|pg_backend_memory_contexts|追加| |
|pg_locks|変更|waitstart 列の追加|
|pg_prepared_statements|変更|custom_plans 列の追加<br>generic_plans 列の追加|
|pg_replication_slots|変更|two_phase 列の追加|
|pg_stat_activity|変更|query_id 列の追加|
|pg_stat_database|変更|以下の列の追加<br>active_time<br>idle_in_transaction_time<br>session_time<br>sessions<br>sessions_abandoned<br>sessions_fatal<br>sessions_killed<br>|
|pg_stat_progress_copy|追加| |
|pg_stat_replication_slots|追加||
|pg_stat_ssl|変更|compression 列の削除 |
|pg_stat_wal|追加| |
|pg_stats_ext|変更|exprs 列の追加 |
|pg_stats_ext_exprs|追加| |

# 変更内容の詳細
## システムテーブル
### pg_attribute
attcompression列が追加された。列単位の(TOAST時の)圧縮方式を指定する。
ALTER TABLEにも以下のようなオプションが追加されている。

```sql
ALTER [ COLUMN ] column_name SET COMPRESSION compression_method
```
compression_methodには`pglz`（デフォルト）か`lz4`を指定する。
なお、psqlのcompression_methodは、psqlの`\d+`メタコマンドでも表示される。

```sql
testdb=# \d+ test
                                           Table "public.test"
 Column |  Type   | Collation | Nullable | Default | Storage  | Compression | Stats target | Description
--------+---------+-----------+----------+---------+----------+-------------+--------------+-------------
 id     | integer |           |          |         | plain    |             |              |
 data   | text    |           |          |         | extended | pglz        |              |
Access method: heap
```
CompressoinはTOAST対象となるようなデータ（Storageが`extended`, `external`）に設定される。このため、上記の例だとdataのみに値が設定されている。
このへんの詳細については別途調査予定。

### pg_inherits
inhdetachpending列の追加。
この列はパーティションが組み込み(attach)/切り離し(detach)状態かを示すフラグ。onならattach状態、offならdetach状態を示す。
まだ、調べてないけど、psqlのメタコマンドでもこの情報をもとにした表示とかも実装されていそうだ。

### pg_proc
prosqlbody列の追加。
この列には"SQL-standard notation"で記述した場合に情報が格納されると書いてあるが、そもそも、"SQL-standard notation"とはなんぞ？
従来、``CREATE FUNCTION``でSQL関数を記述する場合には、``$$``で括った間にSQL「文字列」を記述していたが、SQL標準により近い記述のことらしい。

例えば、引数に1を加えた値を返却する簡単な関数`foo_func`を作ってみる。
従来の記述方式だと、こんな感じになる。

```sql
testdb=# CREATE FUNCTION foo_func( p1 integer)
 RETURNS integer
 LANGUAGE SQL
 IMMUTABLE
AS $function$
SELECT p1 + 1
$function$
;
CREATE FUNCTION
testdb=# SELECT foo_func(1);
 foo_func
----------
        2
(1 row)

testdb=# SELECT p.proname, l.lanname, p.prosqlbody FROM pg_proc p JOIN pg_language l ON (p.prolang = l.oid) WHERE proname = 'foo_func';
 proname  | lanname | prosqlbody
----------+---------+------------
 foo_func | sql     |
(1 row)
```
この場合には、``prosqlbody``列はnullになる。

SQL標準（に近い）記述方法で、上記の``foo_func``を作成し、``prosqlbody``を確認してみる。

```sql
testdb=# CREATE FUNCTION foo_func( p1 integer ) RETURNS integer LANGUAGE SQL IMMUTABLE RETURN p1 + 1;
CREATE FUNCTION
testdb=# SELECT foo_func(1);
 foo_func
----------
        2
(1 row)

testdb=# \x
Expanded display is on.
testdb=# SELECT p.proname, l.lanname, p.prosqlbody FROM pg_proc p JOIN pg_language l ON (p.prolang = l.oid) WHERE proname = 'foo_func';
-[ RECORD 1 ]----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
proname    | foo_func
lanname    | sql
prosqlbody | {QUERY :commandType 1 :querySource 0 :canSetTag true :utilityStmt <> :resultRelation 0 :hasAggs false :hasWindowFuncs false :hasTargetSRFs false :hasSubLinks false :hasDistinctOn false :hasRecursive false :hasModifyingCTE false :hasForUpdate false :hasRowSecurity false :isReturn true :cteList <> :rtable <> :jointree {FROMEXPR :fromlist <> :quals <>} :targetList ({TARGETENTRY :expr {OPEXPR :opno 551 :opfuncid 177 :opresulttype 23 :opretset false :opcollid 0 :inputcollid 0 :args ({PARAM :paramkind 0 :paramid 1 :paramtype 23 :paramtypmod -1 :paramcollid 0 :location 85} {CONST :consttype 23 :consttypmod -1 :constcollid 0 :constlen 4 :constbyval true :constisnull false :location 90 :constvalue 4 [ 1 0 0 0 0 0 0 0 ]}) :location 88} :resno 1 :resname <> :ressortgroupref 0 :resorigtbl 0 :resorigcol 0 :resjunk false}) :override 0 :onConflict <> :returningList <> :groupClause <> :groupDistinct false :groupingSets <> :havingQual <> :windowClause <> :distinctClause <> :sortClause <> :limitOffset <> :limitCount <> :limitOption 0 :rowMarks <> :setOperations <> :constraintDeps <> :withCheckOptions <> :stmt_location 0 :stmt_len 0}

testdb=#
```
``prosqlbody``列に謎の文字列が設定された。
これが、"Pre-parsed SQL function body."と呼ばれるものらしい。

### pg_range
``rngmultitypid``列の追加。
マルチレンジタイプの場合にはここに``pg_type.oid``が設定されるとのこと。
マルチレンジタイプというのが何かを調べる必要があるか・・・。

### pg_statistic_ext
``stxexprs``列の追加。
単純な列参照ではない統計オブジェクト属性の式ツリー。
とのことだが、実際にどういうときにどういう値が入るのかは、拡張統計情報の（おそらく）新機能をきちんと調べないとわからなさそう・・・

### pg_statistic_ext_data
``stxdexpr``列の追加。（調査時点(2021-05-30)ではPostgreSQL Documentが誤っていて、ここが``stxexprs``になっている・・・）
この統計オブジェクトによってカバーされる式のリスト。 
とのことだが、これだけ読んでもやっぱりわからない。拡張統計情報機能の調査が必要そう。

### pg_subscription
``subbinary``列の追加。
これが``true``の場合、サブスクリプションはパブリッシャーがバイナリ形式でデータを送信することを要求します。とのこと。
論理レプリケーションの形式が指定できるということか？

``substream``列の追加。
これが``true``の場合、サブスクリプションは進行中のトランザクションのストリーミングを許可します。とのこと。
論理レプリケーション関連の機能追加もいくつかありそうだな・・・

### pg_type
``typsubscript``列の追加。
配列のハンドラ関数に関するフラグのようだけど、文書読んでも今ひとつ良くわからない。今後調査。

## システムビュー
### pg_backend_memory_contexts
PostgreSQL 14から新規に追加されたシステムビュー。
現在のセッションに接続されているサーバープロセスのすべてのメモリコンテキストを表示する。
メモリコンテキストごとに1行生成される。

PostgreSQLを起動しただけで、おそらくは何行もこのビューの行が見えるようになるのではなかろうか。
詳細の調査は別途実施。
[pg_backend_memory_contextsビューの説明](https://www.postgresql.org/docs/14/view-pg-backend-memory-contexts.html)

### pg_locks
``waitstart``列の追加。
サーバー プロセスがこのロックの待機を開始した時刻.
ロックが保持されている場合は``null``。

### pg_prepared_statements
``custom_plans``列,``generic_plans``列の追加。
カスタムプラン/ジェネリックプランが選択された回数が格納される。

### pg_replication_slots
``two_phase``列の追加
二相コミットの準備されたトランザクションのデコードが有効に鳴っている場合は``true``が設定される。
ストリーミングレプリケーションのスロットの場合は常に``false``が設定される。

### pg_stat_activity
``query_id``列の追加。
このバックエンドの最新のクエリの識別子。
compute_query_idパラメータが無効の場合、またはクエリ識別子を計算するサードパーティモジュールが設定されていない限り、このフィールドはnullになる。

### pg_stat_database
このビューの列追加が何気に多い。なので、ここは表にしてまとめる。

|追加された列|内容|
|:--|:--|
|active_time|このデータベースでの SQL ステートメントの実行にかかった時間 (ミリ秒単位)|
|idle_in_transaction_time|このデータベースでidle in transaction状態の時間 (ミリ秒単位)|
|session_time|このデータベースでデータベース セッションが費やした時間 (ミリ秒) <br>活動統計情報はセッションの状態が変化した場合にのみ更新されるため、セッションが長時間アイドル状態である場合、そのアイドル時間は含まれないことに注意が必要|
|sessions|このデータベースに対して確立されたセッションの合計数|
|sessions_abandoned|クライアントへの接続が失われたために終了した、このデータベースへのデータベース セッションの数|
|sessions_fatal|致命的なエラーによって終了した、このデータベースへのデータベース セッションの数|
|sessions_killed|オペレータの介入によって終了した、このデータベースへのデータベース セッションの数 |

pg_stat_databaseを見るだけでセッションに関する概要がいろいろ見えるように鳴ったのは良さげ。

### pg_stat_progress_copy
PostgreSQL 14から新規に追加されたシステムビュー。
このビューを見てCOPYの進捗を確認可能になるのか。
巨大なデータのCOPYってやきもきするから、この進捗確認機能が実装されると嬉しい人は結構いそう。
[pg_stat_progress_copyビューの説明](https://www.postgresql.org/docs/14/progress-reporting.html#COPY-PROGRESS-REPORTING)
これは、近日中に検証予定。

### pg_stat_replication_slots
PostgreSQL 14から新規に追加されたシステムビュー。
論理レプリケーションスロットごとに 1 行が含まれ、その使用状況に関する統計が表示される。
ストリーミングレプリケーションで使うスロットの情報はここには含まれないように説明からは読める。
[pg_stat_replication_slotsビューの説明](https://www.postgresql.org/docs/14/monitoring-stats.html#MONITORING-PG-STAT-REPLICATION-SLOTS-VIEW)

### pg_stat_ssl
``compression``列の削除。
リリースノートを読むと、

* 以前の PostgreSQLリリースではデフォルトですでに無効になっている。
* 最新の OpenSSL および TLS バージョンのほとんどでサポートされていない。

のでPostgreSQL 14からは列自体削除になったようだ。

### pg_stat_wal
PostgreSQL 14から新規に追加されたシステムビュー。
「クラスタの WAL アクティビティに関するデータが含まれる」という説明があるんだけど、ここでいう「クラスタ」っていうのは、データベースクラスタのことだろうなあ。
で、pg_stat_wal ビューには常に単一の行が存在する、とのこと。
``wal_write_time``や``wal_sync_time``を見ることで、WAL書き込みにどれだけの時間を消費しているかが見えてくるのかな？

[pg_stat_walビューの説明](https://www.postgresql.org/docs/14/monitoring-stats.html#MONITORING-PG-STAT-WAL-VIEW)

### pg_stats_ext
``exprs``列の追加。
うーむ、今日(2021-05-30)時点のPostgreSQL Documentにはこの列が記載されていない・・・。

### pg_stats_ext_exprs
PostgreSQL 14から新規に追加されたシステムビュー。
拡張統計オブジェクトに含まれるすべての式に関する情報へのアクセスを提供し、``pg_statistic_ext``および``pg_statistic_ext_data``に保存された情報を結合する、とのことだが、拡張統計情報のDDLも含めて調査しないとわからないな・・・
[pg_stats_ext_exprsシステムカタログの説明](https://www.postgresql.org/docs/14/view-pg-stats-ext-exprs.html)

# おわりに
今日の調査時点では差分の内容について不明確なものも多いので、今後、他の機能調査結果と合わせて随時補完していきたい。