web-dev-qa-db-ja.com

pg_database_sizeはどの部分で構成されていますか?

DBサイズをグラフ化するmuninプラグインを作成しようとしています。 _pg_database_size_を使用すると同時に、そのコンポーネントもグラフ化したいと思います。

これまでのところ、私は次のことを考え出しました:

_SELECT
    SUM(pg_relation_size(oid, 'main')) AS main_size,
    SUM(pg_relation_size(oid, 'vm')) AS vm_size,
    SUM(pg_relation_size(oid, 'fsm')) AS fsm_size,
    SUM(
        CASE reltoastrelid
        WHEN 0 THEN 0
        ELSE pg_total_relation_size(reltoastrelid)
        END
    ) AS toast_size,
    SUM(pg_indexes_size(oid)) AS indexes_size
    FROM pg_class
    WHERE reltype != 0 -- 0=indices, covered by pg_indexes_size
_

ただし、これらの5つの値を合計すると、_pg_database_size_の結果と同じnotが返されます。大きなDBの場合、違いはそれほど重要ではないようです。

より大きなDBでの例:

_┌──────────┬────────┬─────────┬─────────┬──────────┬───────────────┬──────────────────┬─────────┐
│   main   │   vm   │   fsm   │  toast  │ indexes  │ sum_of_values │ pg_database_size │  diff   │
├──────────┼────────┼─────────┼─────────┼──────────┼───────────────┼──────────────────┼─────────┤
│ 72441856 │ 753664 │ 2392064 │ 4677632 │ 41377792 │ 116 MB        │ 111 MB           │ 5222 kB │
└──────────┴────────┴─────────┴─────────┴──────────┴───────────────┴──────────────────┴─────────┘
(1 row)
_

より小さいDBでの例:

_┌─────────┬────────┬─────────┬────────┬─────────┬───────────────┬──────────────────┬─────────┐
│  main   │   vm   │   fsm   │ toast  │ indexes │ sum_of_values │ pg_database_size │  diff   │
├─────────┼────────┼─────────┼────────┼─────────┼───────────────┼──────────────────┼─────────┤
│ 2809856 │ 385024 │ 1351680 │ 557056 │ 2924544 │ 7840 kB       │ 6642 kB          │ 1198 kB │
└─────────┴────────┴─────────┴────────┴─────────┴───────────────┴──────────────────┴─────────┘
(1 row)
_

何が欠けていますか?

おそらく関連しているかもしれませんが、そうではないかもしれません。彼らは巨大です。私のクエリの何かが間違っていますか?


以下は、さまざまな値を検査するために使用したスクリプトです。

_SELECT
    SUM(pg_relation_size(oid, 'main')) AS main,
    SUM(pg_relation_size(oid, 'vm')) AS vm,
    SUM(pg_relation_size(oid, 'fsm')) AS fsm,
    SUM(
        CASE reltoastrelid
        WHEN 0 THEN 0
        ELSE pg_total_relation_size(reltoastrelid)
        END
    ) AS toast,
    SUM(pg_indexes_size(oid)) AS indexes,
    pg_size_pretty(
        SUM(pg_relation_size(oid, 'main'))::bigint +
        SUM(pg_relation_size(oid, 'vm'))::bigint +
        SUM(pg_relation_size(oid, 'fsm'))::bigint +
        SUM(pg_indexes_size(oid))::bigint +
        SUM(
            CASE reltoastrelid
            WHEN 0 THEN 0
            ELSE pg_total_relation_size(reltoastrelid)
            END
        )::bigint
    ) AS sum_of_values,
    pg_size_pretty(pg_database_size(current_database())) AS pg_database_size,

    pg_size_pretty(
        SUM(pg_relation_size(oid, 'main'))::bigint +
        SUM(pg_relation_size(oid, 'vm'))::bigint +
        SUM(pg_relation_size(oid, 'fsm'))::bigint +
        SUM(pg_indexes_size(oid))::bigint +
        SUM(
            CASE reltoastrelid
            WHEN 0 THEN 0
            ELSE pg_total_relation_size(reltoastrelid)
            END
        )::bigint - pg_database_size(current_database())::bigint
    ) AS diff

FROM pg_class
WHERE reltype != 0;
_
4
exhuma

pg_database_size()は基本的に、$PGDATA/base/oid-of-database(データベースごとのデータディレクトリ)のサイズに加えて、CREATE TABLESPACEで追加されたデフォルト以外のテーブルスペース内のそのようなすべてのディレクトリのサイズをファイルシステムに照会します。

これらのディレクトリに関係に関係のないファイルがある場合、それらもカウントされます。ランダムなデータベースを見ると、その場合のpg_internal.initPG_VERSIONpg_filenode.mapがわかります。これらは合計してディレクトリサイズになり、制御クエリではカウントされません。

浮遊データファイルが存在する可能性もあります。具体的な例については、 部分的に構築され、停電によって終了したインデックスによって使用されたスペースを再利用する方法 を参照してください。また、pg_classに対してクエリを実行しても、定義から見つけることはできず、ディスク上のデータベースサイズでカウントされます。

クエリに関しては、オブジェクトサイズの合計を取得する目的でのみ、より単純なバージョンをお勧めします。

select sum(pg_total_relation_size(oid)) 
from pg_class
where relkind in ('r','m','S')
  and not relisshared

共有関係はこのクエリから削除されることに注意してください(not relisshared)。共有オブジェクトはすべてのデータベースから見ることができ、どのデータベースのディレクトリにも属していません。それらは$PGDATA/globalにあります。サイズが大きくなると予想される共有テーブルの1つは pg_shdepend です。元のクエリでこれを見落とすと、過大評価になります(トーストテーブルに関する@jjanesコメントに加えて)。

4
Daniel Vérité

トーストテーブルを2回カウントしています。いったん所有者の下にpg_total_relation_size(reltoastrelid)として、再びpg_classの自分のエントリの下に。必要なものをフィルタリングするには、reltypeではなくrelkindを使用する必要があります。

また、RDBMSをこの範囲までマイクロ管理しようとしても、ほとんど効果がありません。

4
jjanes