【はじめたばかりで1/3も書いてない】 OracleとPostgreSQLのシステムビュー/カタログ 比較

自分用メモ
OracleのシステムビューとPostgreSQLの各種カタログ(テーブルとかビューとか)の対応を緩くまとめる。

メモ書きをはじめたばかりで、内容には非常に多くの間違いが混じっているはずので信じないこと。
徐々に完成度を上げていく予定。

(なんとか)対応付け可能なもの

プロセス関係

基本的にPostgreSQLにはプロセス情報を得るためのシステムカタログがない。例外はBackgroundWriterのみ(pg_bgwriter)。

Oracle 説明 PostgreSQLの状況
V$PROCESS Oracleのプロセス情報 上記のようにPostgreSQLにはない。psコマンドで眺めるだけ。
V$BGPROCESS 現在のバックグランドプロセスの情報 同上

ただし、後述するpg_stat_activityのpidでセッション毎のプロセスid、stateでバックエンドプロセスの状態(active|idle|idle in transaction|idle in transaction (aborted)|fastpath function call|disabled)は分かる。

パラメータ

PostgreSQLの場合、postgresql.confでの設定がほぼ全て。
pg_settingsビューで表示できる。

Oracle 説明 PostgreSQLの状況
V$PARAMETER、V$OPTION 有効なパラメータやオプション pg_settingsビューがある。また”SHOW ALL”でパラメータを表示できる。
SESSIONの情報

PostgreSQLのセッション情報はpg_stat_activityに集約されている。よって、ここにない情報はPostgreSQLでは得られないということになる。

例えば、実行中のqueryは分かるが、そのqueryによってアクセスされているテーブルはqueryを目視して確認しなければならない。そうして目視したテーブル名からpg_classなど使って徐々にテーブルの情報を探り出すしかない。

Oracle 説明 PostgreSQLの状況
V$SESSION 現在接続されているセッション pg_stat_activity
V$SESSION_LONGOPS 処理に時間がかかっているセッション pg_stat_activityのxact_startとcurrent_timestampの差をみればよい。ただし、操作対象となっているリレーションはqueryから目視するしかない。

長くかかっているセッション、というかトランザクションを知るには以下のSELECT文を実行する。

SELECT pid, waiting, (current_timestamp - xact_start)::interval(3)
 AS duration, query FROM pg_stat_activity WHERE pid <> pg_backend_pid();


なお、pg_stat_activityの情報は、バックエンド単位の統計情報関数でも得られる。

LOCK

これはばっちり対応がつく。

Oracle PostgreSQL
V$LOCK pg_locks
Buffer Cache

これが書きたくてこのエントリーをはじめたようなもの。

PostgreSQLには標準ではshared_buffersの中身を知る手だてがない。しかしcontribのpg_buffercacheを使うとある程度わかる。

Oracle 説明 PostgreSQLの状況
V$CACHE メモリ上のオブジェクトを特定する pg_buffercacheを使ってqueryを組み立てると、ある程度わかる。

まだqueryが複雑過ぎて表にだせるレベルではないけども、例えばshared_buffersの利用率なら以下のqueryでそれっぽいのが表示できる。

-- 作成途中。間違ってる可能性あり。
WITH 
bc AS (SELECT count(*) AS block_num 
      	  FROM (SELECT DISTINCT ON (relfilenode,relforknumber,relblocknumber) relfilenode 
       	      	   FROM pg_buffercache WHERE relfilenode IS NOT NULL OR relfilenode != 0) AS a),
bs AS (SELECT cast(current_setting('block_size') AS integer) AS block_size),
sb AS (SELECT cast(setting AS bigint) shared_buffers 
           FROM pg_settings WHERE name = 'shared_buffers')
SELECT 
pg_size_pretty(bc.block_num * bs.block_size) AS "used buffer size",
pg_size_pretty(sb.shared_buffers * bs.block_size) AS "total buffer size",
CASE WHEN bc.block_num = 0 
THEN  0.00
ELSE round(cast(cast(bc.block_num AS numeric)/cast(sb.shared_buffers AS numeric) AS  numeric) ,2) 
END AS "usage ratio"
FROM bc, bs, sb;
 used buffer size | total buffer size | usage ratio 
------------------+-------------------+-------------
 7856 kB          | 20 MB             |        0.38
(1 row)

Oracleの共有プール関係のビュー(V$SGASTAT、V$DB_OBJECT_CHACE、V$SQLAREA)あたりは、PostgreSQLに共有プールという概念がないから対応不可でOK?


(私が今のところ)対応付けできないもの

OraclePostgreSQLもよく知らないので(今のところ)対応付けできていないもの。

TABLE,INDEX,DATABASEの統計情報

Oracleではなんでしたっけ?
PostgreSQLにはこんなものがあるのですが。

システムカタログ 説明
pg_stat_database データベースの統計情報。
pg_stat_all_tables テーブル毎の統計情報
pg_statio_all_tables テーブル毎の統計情報。バッファのヒット回数などIOレベルの情報
pg_stat_all_indexes インデックス毎の統計情報
pg_statio_all_indexes インデックス毎の統計情報。バッファのヒット回数などIOレベルの情報

因みにこれらのシステムカタログの情報は、当然ながらリレーションに紐付けされている。セッションやquery、トランザクション毎にリレーションの統計情報がどうなっているかは分からない。例えば、あるセッションがあるリレーションに読み書きしたブロック数などは分からない。




(概念的に違いすぎて)対応付け不可能なもの

TABLESPACE

OraclePostgreSQLでは"TABLESPACE"の意味が全く異なるので、比較しようがない。

Oracle 意味 PostgreSQLで無意味な理由(補足)
V$TABLESPACE Oracleでの表領域一覧 概念的に異なる。PostgreSQL的なTABLESPACEならば\dbか、pg_tablespaceで得られる。
OracleのTABLESPACEの空き(FREE): DBA_FREE_SPACE

これもPostgreSQLには概念的に存在しないものだけども、TALBLESPACEでなくTABLE(やINDEX)のFREE SPACEならば
contribのpg_freespacemapを使うとわかったりする。

メモ書きとして、書いておく。

V$TRANSACTION

「おいおいPostgreSQLにもトランザクションはあるだろ!M○S○Lみたいなポンコツとは違うだろ」という声も聞こえますが、OracleのV$TRANSACTIONはUNDO領域の情報だったりするのでPostgreSQLには関係ないわけですね*1

*1:PostgreSQLは追記型でUNDOログも持っていない