テーブルとインデックスの肥大化は、VACUUM オペレーションがテーブルに対するデータ操作言語(DML)の速度に追いつかない場合に発生します。トランザクションでそのスペースを再利用できるため、テーブルとインデックスの肥大化は避けられず、一般的に許容されます。過剰な肥大化は、クエリ時間の遅延、I/O の増加、共有バッファとキャッシュの使用効率の低下、ストレージ コストの増加など、パフォーマンスの問題を引き起こします。
ブロートを推定する最善の方法は、pgstattuple モジュールを使用することです。ただし、拡張機能がリレーションのすべてのページを読み取る必要がある場合、pgstattuple の使用は効率的ではありません。pgstattuple を使用できない場合は、他のスクリプトを使用してブロートを推定できますが、この方法では精度が低下します。
pgstattuple の出力を読み取る
pgstattuple を使用してテーブルまたはインデックスの物理ストレージ特性をレポートすると、出力は次の形式になります。
> SELECT * FROM pgstattuple('large_table');
-[ RECORD 1 ]------+-----------
table_len | 7431888896
tuple_count | 66666666
tuple_len | 2796296271
tuple_percent | 37.63
dead_tuple_count | 0
dead_tuple_len | 0
dead_tuple_percent | 0
free_space | 3873153652
free_percent | 52.12
出力の説明は次のとおりです。
table_len(7431888896)- テーブルの合計サイズ(バイト単位)。これには、ライブ タプル、デッド タプル、空き容量がすべて含まれます。この場合、
large_tableは約 7,088 GB を占有します。 tuple_count(66666666)- テーブル内のライブタプル(表示されアクティブな行)の数を表します。このテーブルには約 6,600 万件のアクティブな行が含まれています。
tuple_len(2796296271)- すべてのライブタプルの合計長(バイト単位)。約 2.6 GB です。
tuple_percent(37.63)ライブタプルが占める
table_lenの割合。次のように計算します。(
tuple_len/table_len)× 100 =(2796296271/7431888896)× 100 ≈37.63パーセントこの出力は、アクティブなデータがテーブルのディスク容量の 40% 未満であることを示しています。
dead_tuple_count(0)デッドタプルの数。更新または削除後にバキューム オペレーションでまだ削除されていない行の数です。値
0は、テーブルがクリーンで、再利用を待機しているデッドタプルがないことを意味します。これは多くの場合、VACUUM(自動バキューム)がテーブルで効率的に実行されていることを示しています。dead_tuple_len(0)すべてのデッドタプルの合計長(バイト単位)。
dead_tuple_countと同様に、0の値は、デッド行がスペースを消費しないことを意味します。dead_tuple_percent(0)デッドタプルが占める
table_lenの割合。次のように計算します。(
dead_tuple_len/table_len)× 100 = (0/7431888896)× 100 =0%free_space(3873153652)この値は、テーブルのデータページ内の空き容量を表します。この領域は、テーブルの拡張を必要とせずに、新しい挿入や更新に再利用できます。これは、約 3.7 GB の空き容量があることを示しています。
free_percent(52.12)この値は、
table_lenの空き容量の割合を表します。計算式は次のとおりです。(
free_space/table_len)× 100 =(3873153652/7431888896)× 100 ≈52.12パーセント
クエリを使用して膨張を見積もる
システム カタログ テーブルに対するクエリを使用して bloat を見積もることができますが、この方法は pgstattuple などの拡張機能を使用するよりも精度が低くなります。PostgreSQL テーブルの肥大化チェックなどのスクリプトを使用する場合は、テーブルの統計情報を最新の状態にする必要があります。そうしないと、推定値が不正確になります。
クエリの出力を pgstattuple モジュールと比較すると、推定値は比較可能ですが、ブロートの正確な測定値ではありません。SQL クエリは PostgreSQL の累積統計エンジンに依存しますが、モジュールは実際のデータページを読み取るため、モジュールの方がブロートの正確な指標となります。
次の例では、large_table という名前のテーブルの PostgreSQL でテーブルの肥大化を分析する 2 つの異なるメソッドの出力を比較しています。
> SELECT * FROM pgstattuple('large_table');
-[ RECORD 1 ]------+-----------
table_len | 2475892736
tuple_count | 22000000
tuple_len | 922925931
tuple_percent | 37.28
dead_tuple_count | 0
dead_tuple_len | 0
dead_tuple_percent | 0
free_space | 1293696900
free_percent | 52.25
Vs.
-[ RECORD 1 ]+------------
databasename | postgres
schemaname | public
tablename | large_table
can_estimate | t
est_rows | 21965400
pct_bloat | 54
mb_bloat | 1269.24
table_mb | 2361.195
アドレスの肥大化
ブロートは次の方法で管理できます。それぞれにメリットとデメリットがあるため、慎重な計画が必要です。
- フル掃除を実行します。このオペレーションでは、バキュームの期間中、テーブル全体がロックされ、ダウンタイムが発生します。
- データを新しいテーブルに移動します。このメソッドを使用するには、テーブルの変更を停止して、変更が新しいリレーションに転送されないようにする必要があります。
pg_squeezeを使用します。この拡張機能は、オンラインでのブロートを軽減します。この拡張機能は、シャドー テーブルを作成し、すべてのデータを挿入してから、最後のステップ(肥大化したテーブルを新しく作成された肥大化していないテーブルに切り替える)まで、レプリケーション スロットを使用してテーブルの変更を維持します。次に、膨張していないテーブルを移動して膨張したテーブルを置き換えるために、短いテーブルロックをリクエストします。この方法では、オペレーションの実行中にオブジェクトの 2 倍のスペースが必要になりますが、通常のオペレーションへの影響は最小限に抑えられます。