Pivotal Knowledge Base

フォローする

"VACUUM ANALYZE" が必要なテーブルの確認

環境

製品 バージョン
Pivotal Greenplum(GPDB) 全てのバージョン

目的

あるテーブルに対して VACUUM ANALYZE が必要な理由は 3 つある。

  • テーブル肥大化を防ぐために、破棄された行から領域を回収するため(VACUUM)
  • age 値が高いテーブルのトランザクション age 値を減らす(VACUUM)
  • 当該テーブルを対象とするクエリーが最適な実行計画を維持するために統計値を収集(ANALYZE)

本記事では、上述の理由について詳細に述べる。

解決策

破棄された行から領域を回収
 
"gp_toolkit" 管理スキーマに、潜在的なテーブル肥大化を示すいくつかのビューが存在する。これらのビューでは、テーブルのディスク上における実サイズと統計値から計算された「期待される」サイズとを比較している。したがって、それらのビューから結果を取得する前に、対象テーブルに対して統計値修正のため ANALYZE を実行する必要がある。
  • gp_bloat_diag
  View "gp_toolkit.gp_bloat_diag"
   Column    |  Type   | Modifiers 
-------------+---------+-----------
 bdirelid    | oid     |              - OID
 bdinspname  | name    |              - Schema name
 bdirelname  | name    |              - Table name
 bdirelpages | integer |              - Number of table pages
 bdiexppages | numeric |              - Number of expected pages
 bdidiag     | text    |              - Diagnostic: "no bloat"/"moderate bloat"/"significant bloat"

例: 
lpetrov=# select * from gp_toolkit.gp_bloat_diag;
 bdirelid | bdinspname | bdirelname | bdirelpages | bdiexppages |                bdidiag                
----------+------------+------------+-------------+-------------+---------------------------------------
   353016 | public     | t1         |         978 |           1 | significant amount of bloat suspected
(1 row)
  • gp_bloat_expected_pages
lpetrov=# \d gp_toolkit.gp_bloat_expected_pages 
View "gp_toolkit.gp_bloat_expected_pages"
   Column    |  Type   | Modifiers 
-------------+---------+-----------
 btdrelid    | oid     |             - OID
 btdrelpages | integer |             - Number of table pages
 btdexppages | numeric |             - Number of expected pages

例:

lpetrov=# select * from gp_toolkit.gp_bloat_expected_pages where btdrelid = 't1'::regclass;
 btdrelid | btdrelpages | btdexppages 
----------+-------------+-------------
   353016 |         978 |           1
(1 row)

gp_bloat_expected_pages は全てのテーブルデータを表示する一方、gp_bloat_diag はテーブル肥大化が疑われるテーブル(程度が moderate か siginificant)のデータのみ表示する。

age 値が高いテーブルのトランザクション age 値を減らす

これは二段階の操作を経て行う。

  • age 値が高いデータベース・セグメントを特定
SELECT 
    -1, datname, age(datfrozenxid) 
FROM pg_database
UNION ALL
SELECT 
    gp_segment_id, datname, age(datfrozenxid)
FROM gp_dist_random('pg_database')
ORDER BY 3 DESC
  • 当該データベース・セグメント内で "VACUUM" が必要なテーブルを特定
SELECT 
    coalesce(n.nspname, ''), 
    relname, 
    relkind, 
    relstorage, 
    age(relfrozenxid)
FROM 
    pg_class c 
    LEFT JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE 
    relkind = 'r' AND relstorage NOT IN ('x', 'a', 'c')
ORDER BY 5 DESC

ヒント: ある一定数よりも高い age 値のテーブルのみを表示するために LIMIT 句の代わりに "WHERE" 句も使用可能である。

当該テーブルを対象とするクエリーが最適な実行計画を維持するために統計値を収集

現状、EXPLAIN ANALYZE の出力内容を調査し、テーブルスキャンにより得られる推定行値と実際の行数を比較する以外に、統計値が古いテーブルを見つける方法はない。

推定値を得るには以下の 2 つの方法がある。

  • gp_toolkit.gp_stats_missing - カタログ内で統計情報がないテーブルを示すビュー。
  • pg_stat_last_operation - 直近の ANALYZE がいつ行われたか確認する。テーブルに対して非常に多くの更新が行われていると、そのうち ANALYZE が必要となるであろう。

コメント

Powered by Zendesk