PostgreSQL 9 min read

PostgreSQLのテーブルサイズ確認 ― pg_relation_sizeとpg_total_relation_sizeの違い

※この記事にはアフィリエイト広告(プロモーション)が含まれます。

テーブルの大きさを測る関数は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のテーブル一覧

PostgreSQL をもっと深く知るための本

PostgreSQL実践入門 ──アーキテクチャ、運用監視、性能改善

技術評論社・2026年2月

アーキテクチャから運用監視・性能改善までを扱う。付録に PostgreSQL 18 の新機能と設定項目の差分がある。

Amazonで見る

[改訂3版]内部構造から学ぶPostgreSQL ―設計・運用計画の鉄則

技術評論社・2022年11月・PostgreSQL 14 ベース

内部構造の理解から、設計と運用計画の立て方を学ぶ。

Amazonで見る

Amazonのアソシエイトとして、FIRE SE は適格販売により収入を得ています。