PostgreSQLでデータベース・テーブル・インデックス容量とレコード数を一発で取得する方法

Database
データベース・テーブル・インデックス容量とレコード数を取得する方法

PostgreSQLデータベースのデータベース容量(サイズ)、テーブルの容量(サイズ)、インデックスの容量(サイズ)、テーブルに存在するレコード数を調べるSQLです。テーブル容量とインデックス容量とレコード数を一度に調べるSQLも併せて記載しています。実際にテスト用のデータベース・テーブル・インデックスを作成して容量を確認してみます。

テスト用のテーブルとインデックスを生成する

まずPostgreSQLデータベースのテーブルやインデックスの容量を調べられるようにするためのテーブルを用意します。最も手軽なのはpgbenchコマンドを使って自動でテスト用のテーブルを作成することです。以下のようにpgbenchコマンドを実行します。

$ pgbench -i -s 100 -d test -U postgres

すると以下のようにpgbench処理が実行され、テーブルとインデックスが作成されるとともに、大量のテストデータが生成されます。

$ pgbench -i -s 100 -d test -U postgres
dropping old tables...
NOTICE:  table "pgbench_accounts" does not exist, skipping
NOTICE:  table "pgbench_branches" does not exist, skipping
NOTICE:  table "pgbench_history" does not exist, skipping
NOTICE:  table "pgbench_tellers" does not exist, skipping
creating tables...
generating data (client-side)...
10000000 of 10000000 tuples (100%) done (elapsed 18.46 s, remaining 0.00 s)
vacuuming...
creating primary keys...
done in 25.13 s (drop tables 0.00 s, create tables 0.01 s, client-side generate 18.62 s, vacuum 2.76 s, primary keys 3.73 s).

以下のようにpg_bench_から始まる名称のテーブルが4つ生成されます。またそれに付随して3つのインデックスも作成されています。

$ psql -U postgres -d test
psql (13.18)
Type "help" for help.

test=# \dt
               List of relations
+--------+------------------+-------+----------+
| Schema |       Name       | Type  |  Owner   |
+--------+------------------+-------+----------+
| public | pgbench_accounts | table | postgres |
| public | pgbench_branches | table | postgres |
| public | pgbench_history  | table | postgres |
| public | pgbench_tellers  | table | postgres |
+--------+------------------+-------+----------+
(4 rows)

test=# \di
                           List of relations
+--------+-----------------------+-------+----------+------------------+
| Schema |         Name          | Type  |  Owner   |      Table       |
+--------+-----------------------+-------+----------+------------------+
| public | pgbench_accounts_pkey | index | postgres | pgbench_accounts |
| public | pgbench_branches_pkey | index | postgres | pgbench_branches |
| public | pgbench_tellers_pkey  | index | postgres | pgbench_tellers  |
+--------+-----------------------+-------+----------+------------------+
(3 rows)

そしてそれぞれのテーブルには以下の件数のデータが自動生成されています。

test=# SELECT COUNT(*) FROM pgbench_accounts;
+----------+
|  count   |
+----------+
| 10000000 |
+----------+
(1 row)

test=# SELECT COUNT(*) FROM pgbench_branches;
+-------+
| count |
+-------+
|   100 |
+-------+
(1 row)

test=# SELECT COUNT(*) FROM pgbench_history;
+-------+
| count |
+-------+
|     0 |
+-------+
(1 row)

test=# SELECT COUNT(*) FROM pgbench_tellers;
+-------+
| count |
+-------+
|  1000 |
+-------+
(1 row)

テーブル容量とインデックス容量とレコード数を一度に調べるSQL

テーブルに格納されているデータの容量

SELECT
  oid
  ,table_schema
  ,table_name
  ,row_estimate
  ,pg_size_pretty(total_bytes) AS total
  ,pg_size_pretty(index_bytes) AS index
  ,pg_size_pretty(toast_bytes) AS toast
  ,pg_size_pretty(table_bytes) AS table
FROM (
  SELECT *, total_bytes-index_bytes-coalesce(toast_bytes,0) AS table_bytes
  FROM (
      SELECT
        c.oid
        ,nspname AS table_schema
        ,relname AS table_name
        ,c.reltuples::numeric AS row_estimate
        ,pg_total_relation_size(c.oid) AS total_bytes
        ,pg_indexes_size(c.oid) AS index_bytes
        ,pg_total_relation_size(reltoastrelid) AS toast_bytes
      FROM pg_class c
      LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
      WHERE relkind = 'r'
  ) a
) a;

このSQLを実行すると、以下のような結果が得られます。テーブルのサイズ、インデックスのサイズ、そして総サイズ、さらに見積もられたレコード数を一度に取得することが出来ます。

+-------+--------------+------------------+--------------+---------+---------+-------+---------+
|  oid  | table_schema |    table_name    | row_estimate |  total  |  index  | toast |  table  |
+-------+--------------+------------------+--------------+---------+---------+-------+---------+
| 25032 | public       | pgbench_accounts |     10000000 | 1495 MB | 214 MB  |       | 1281 MB |
| 25035 | public       | pgbench_branches |          100 | 56 kB   | 16 kB   |       | 40 kB   |
| 25026 | public       | pgbench_history  |            0 | 0 bytes | 0 bytes |       | 0 bytes |
| 25029 | public       | pgbench_tellers  |         1000 | 120 kB  | 40 kB   |       | 80 kB   |
+-------+--------------+------------------+--------------+---------+---------+-------+---------+
(4 rows)

それぞれの項目は次の通りです。

oidテーブルを識別するための一意なID
table_schemaテーブルが属するスキーマ名
table_nameテーブル名
row_estimateテーブルの見積もり行数
totalテーブルとインデックスの合計容量
indexインデックスの容量
toast非常に長いデータを格納した際のサイズ
tableテーブル単体の容量

全てのデータベース容量を調べるSQL

PostgreSQLサーバーのインスタンス内に存在する全てのデータベースの容量を取得するには次のSQLを実行します。

SELECT
  db.datname AS Name
  ,pg_catalog.pg_get_userbyid(db.datdba) AS Owner
  ,CASE WHEN pg_catalog.has_database_privilege(db.datname, 'CONNECT')
        THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(db.datname))
        ELSE 'No Access'
   END as Size
FROM pg_catalog.pg_database db
ORDER BY
  CASE WHEN pg_catalog.has_database_privilege(db.datname, 'CONNECT')
       THEN pg_catalog.pg_database_size(db.datname)
       ELSE NULL
  END DESC;

すると次のように全てのデータベースの容量を取得することが出来ます。

+-----------+-----------------+---------+
|   name    |      owner      |  size   |
+-----------+-----------------+---------+
| test      | radiuslog_owner | 1503 MB |
| postgres  | postgres        | 8141 kB |
| template0 | postgres        | 8117 kB |
| template1 | postgres        | 7181 kB |
+-----------+-----------------+---------+
(4 rows)

テーブル容量を取得して、サイズの大きな順に表示するSQL

存在するテーブルのサイズを取得して、結果をサイズの大きなテーブル順に表示するSQLです。

SELECT
  pn.nspname || '.' || pc.relname AS "relation",
  pg_size_pretty(pg_relation_size(pc.oid)) AS "size"
FROM pg_class pc
LEFT JOIN pg_namespace pn ON (pn.oid = pc.relnamespace)
WHERE pn.nspname NOT IN ('pg_catalog', 'information_schema')
AND pn.nspname = 'public'
ORDER BY
  pg_relation_size(pc.oid) DESC;

実行すると次のようにサイズの大きなテーブルから順に表示されます。

+------------------------------+------------+
|           relation           |    size    |
+------------------------------+------------+
| public.pgbench_accounts      | 1281 MB    |
| public.pgbench_accounts_pkey | 214 MB     |
| public.pgbench_tellers       | 48 kB      |
| public.pgbench_tellers_pkey  | 40 kB      |
| public.pgbench_branches_pkey | 16 kB      |
| public.pgbench_branches      | 8192 bytes |
| public.pgbench_history       | 0 bytes    |
+------------------------------+------------+
(7 rows)

まとめ

PostgreSQLのテーブル、インデックスの容量(サイズ)、レコード数を一度に調べられるSQLは非常に便利ですので是非活用していただければと思います。またデータベースの容量を確認できるSQLも記載しました。

タイトルとURLをコピーしました