Pivotal Knowledge Base

フォローする

HowTo - 肥大分を差し引いたテーブルサイズの測定

問題

特定のテーブルに対して、肥大分を差し引いた実データサイズを知るにはどうしたらよいのか?

解決策

以下のクエリーにて、"Expected" は期待されるテーブルサイズ(すなわち、肥大化がないと考えた場合)を意味し、"Reclaimable" あるいは "Claimable" は実テーブルサイズから期待されるテーブルサイズを引いた差分(回収可能なテーブルサイズ)を意味する。

クエリー

-- 極度に肥大化したテーブルからのみ、期待されるテーブルサイズと回収可能なテーブルサイズを取得(すなわち、データベース上で最も肥大化したテーブルのみから列挙)

SELECT bdinspname||'.'||bdirelname "Relation name",
	bdirelpages::bigint "Current Pages",
        round((bdirelpages*33)/1024)::bigint "Current Size(MB)",
	bdiexppages::bigint "Expected Pages",
	round((bdiexppages*33)/1024)::bigint "Expected Size(MB)",
	(bdirelpages - bdiexppages)::bigint "Claimable Pages",
	round(((bdirelpages - bdiexppages)*33)/1024)::bigint "Claimable Size(MB)",
	bdidiag "Comments"
FROM gp_toolkit.gp_bloat_diag
ORDER BY 6;

-- データベースにおける全てのテーブルから、期待されるテーブルサイズと回収可能なテーブルサイズを取得

SELECT n.nspname||'.'||c.relname "Relation Name",
	btdrelpages::bigint "Current Pages",
        round((btdrelpages*33)/1024)::bigint "Current Size(MB)",
	btdexppages::bigint "Expected Pages",
	round((btdexppages*33)/1024)::bigint "Expected Size(MB)",
	(btdrelpages - btdexppages)::bigint "Claimable Pages",
	round(((btdrelpages - btdexppages)*33)/1024)::bigint "Claimable Size(MB)"
FROM gp_toolkit.gp_bloat_expected_pages e, pg_class c, pg_namespace n 
WHERE e.btdrelid=c.oid 
AND n.oid=c.relnamespace 
ORDER BY 6;

注意:

  1. 上述のクエリーで得られる値は概算値であり、テーブルの統計値に依存する。したがって、できるだけ近い値となるようテーブルに analyze を実施しておきたい。
  2. 上述のクエリーで使用されている 33 という値は、32kb(32 * 1024)を丸めた値であり、ページ数が多すぎる場合の整数型のバッファー制限超え(ERROR: integer out of range)を回避するための措置である。

どのように動作し計算されるか?

テーブルに肥大化傾向が見られるか知るため、gp_toolkit.gp_bloat_diag の内容を確認する。

flightdata=# select * from gp_toolkit.gp_bloat_diag;
 bdirelid | bdinspname | bdirelname | bdirelpages | bdiexppages |              bdidiag
----------+------------+------------+-------------+-------------+------------------------------------
    92783 | public     | test2      |      618870 |       71503 | moderate amount of bloat suspected
(1 row)

さらなる確認のため pg_class の値を参照する。

flightdata=# select relname,relpages,reltuples::bigint from pg_class where relname='test2';
 relname | relpages | reltuples
---------+----------+-----------
 test2   |   618870 |  71000000
(1 row)

gp_bloat_diag からの出力を元に、上述の例の場合、現在割り当てられた OS のページ数は618870 であり、テーブルにおける実データから想定されるページ数は 71503 である。

GPDB においては、1 OS ページは 32kb(すなわち、32 * 1024b)に等しい。

したがって、上述の例でテーブルに割り当てられた現在のサイズは 618870 * 32kb = およそ 19 gb である。

また、期待されるページサイズは、71503 * 32kb = およそ 2gb である。

実際には、テーブルの現在のサイズは以下のように取得する。

flightdata=# SELECT pg_size_pretty(pg_relation_size('test2'));
 pg_size_pretty
----------------
 19 GB
(1 row)

テーブル肥大化を完全に除去する(vacuum full あるいはこちらの記事で言及されている他の方法のいずれでも良い)。ここでは、vacuum full を行うものとする。

flightdata=# vacuum full test2;
VACUUM

次に analyze を実行する。

flightdata=# analyze test2;
ANALYZE

現在のテーブルサイズは、上述の概算値と同じくおよそ 2gb である。

flightdata=# SELECT pg_size_pretty(pg_relation_size('test2'));
 pg_size_pretty
----------------
 2441 MB
(1 row)

flightdata=# select relname,relpages,reltuples::bigint from pg_class where relname in ('test2');
 relname | relpages | reltuples
---------+----------+-----------
 test2   |    78108 |  71000168
(1 row)

注意: 以上はあくまでも概算であるが、肥大化したテーブルの再分散配置や vacuum の実行で、どのくらい無駄な領域を回収できるか参考にしていただきたい。

コメント

Powered by Zendesk