※この記事にはアフィリエイト広告(プロモーション)が含まれます。
テーブルの大きさを測る関数は4つあり、含む範囲が違います。この記事の出力は PostgreSQL 18.6(Ubuntu 26.04)で採りました。
まず見る(結論)
SELECT pg_size_pretty(pg_relation_size('docs')) AS heap,
pg_size_pretty(pg_table_size('docs')) AS table_size,
pg_size_pretty(pg_indexes_size('docs')) AS indexes,
pg_size_pretty(pg_total_relation_size('docs')) AS total;
heap | table_size | indexes | total
---------+------------+---------+-------
1256 kB | 54 MB | 1088 kB | 55 MB
| 関数 | 含むもの |
|---|---|
pg_relation_size |
本体(main)だけ。TOAST もインデックスも含まない |
pg_table_size |
本体+TOAST+FSM・VM。インデックスは含まない |
pg_indexes_size |
そのテーブルのインデックスの合計 |
pg_total_relation_size |
全部(pg_table_size + pg_indexes_size) |
ディスクをどれだけ使っているかを見るなら pg_total_relation_size を使います。
pg_relation_size が小さすぎるとき(TOAST)
上の docs は1行に約2.5KBの文字列を入れた2万行の表です。pg_relation_size は 1256 kB しかなく、残りの 52 MB は TOAST テーブルにありました。
SELECT c.relname, c2.relname AS toast, pg_size_pretty(pg_relation_size(c.reltoastrelid)) AS toast_size
FROM pg_class c JOIN pg_class c2 ON c2.oid = c.reltoastrelid WHERE c.relname = 'docs';
relname | toast | toast_size
---------+----------------+------------
docs | pg_toast_16837 | 52 MB
長い text の値は本体とは別の TOAST テーブルに格納されます。pg_relation_size だけで判断すると、大きい表を小さいと読み違えます。
インデックスごとのサイズ・psql のメタコマンド
SELECT indexrelname, pg_size_pretty(pg_relation_size(indexrelid))
FROM pg_stat_user_indexes WHERE relname = 'docs';
docs_pkey | 456 kB
docs_title | 632 kB
\dt+ docs
Schema | Name | Type | Owner | Persistence | Access method | Size | Description
--------+------+-------+----------+-------------+---------------+-------+-------------
public | docs | table | postgres | permanent | heap | 54 MB |
\dt+ の Size は 54 MB で、pg_table_size と同じ値です。インデックスは \di+ で1本ずつ出ます。
大きい順に一覧する
SELECT n.nspname || '.' || c.relname AS table,
pg_size_pretty(pg_total_relation_size(c.oid)) AS total,
pg_size_pretty(pg_relation_size(c.oid)) AS heap,
pg_size_pretty(pg_indexes_size(c.oid)) AS idx,
c.reltuples::bigint AS rows_est
FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r','p','m')
AND n.nspname NOT IN ('pg_catalog','information_schema')
ORDER BY pg_total_relation_size(c.oid) DESC LIMIT 5;
table | total | heap | idx | rows_est
-------------+-------+------------+---------+----------
public.docs | 55 MB | 1256 kB | 1088 kB | 20000
public.emp | 16 kB | 8192 bytes | 0 bytes | -1
rows_est は統計の推定値です。一度も ANALYZE されていない表は -1 になりました。データベース全体の大きさは pg_database_size で見ます(データベース一覧の記事)。
名前の指定でつまずくところ
| 書き方 | 結果 |
|---|---|
pg_relation_size('nosuch') |
ERROR: relation "nosuch" does not exist |
pg_relation_size('Orders')("Orders" で作った表) |
ERROR: relation "orders" does not exist。小文字に変換される |
pg_relation_size('"Orders"') |
取れる |
pg_relation_size('docs') と pg_relation_size('s1.docs') |
別の値。スキーマを省くと search_path の先頭(public)の表になる |
表の所有者でなく、表への権限も無い一般ユーザーでも、サイズは取れました。
pg_size_pretty の単位
pg_size_pretty は 1024 単位で、10 kB 未満は bytes のまま表示します。10239 は 10239 bytes、10240 は 10 kB、1048576 は 1024 kB でした。並べ替えや比較は pg_size_pretty を通す前の数値で行います。
DELETE しても減らない
| 操作 | pg_total_relation_size |
|---|---|
| 2万行 | 55 MB |
| 半分を DELETE | 55 MB |
| VACUUM | 55 MB |
| VACUUM FULL | 28 MB |
VACUUM FULL は実行中に表を排他ロックします。詳しくは VACUUM の記事 を参照してください。
実ファイルの場所は pg_relation_filepath('docs') で分かります(base/16828/36854 のような、データディレクトリからの相対パス)。
関連: PostgreSQLのVACUUM / PostgreSQLのデータベース一覧 / PostgreSQLのテーブル一覧