【テクニカル・上級編】 HOT更新 (Heap Only Tuple) – PostgreSQL

結局、インデックスが「重い」原因は何か?——PostgreSQLの隠れた功労者「HOT更新」の話

データベースエンジニアとして長く現場にいると、必ず一度は「更新処理が急に遅くなった」「テーブルの肥大化が止まらない」という壁にぶつかります。特にPostgreSQLを使っていると、MVCC(多版同時実行制御)の仕組み上、データ更新が「DELETE + INSERT」として扱われるという事実は避けて通れません。

ここで多くのエンジニアが頭を悩ませるのが、インデックスのメンテナンスコストです。更新のたびにすべてのインデックスエントリを作り直していたら、システムは悲鳴を上げますよね。

そんなとき、我々を救ってくれる静かなるヒーローが HOT (Heap Only Tuple) 更新です。今日は、この少し地味ながらも極めて重要な最適化技術について、内部構造まで深掘りしてみましょう。

—

HOT更新がもたらす「無駄の排除」

通常、PostgreSQLでレコードを更新すると、古いタプル(Dead Tuple)を残し、新しいタプルをヒープ領域の別の場所に作成します。もしインデックス列を更新したなら、当然インデックスにも新しいエントリを追加し、古いエントリを無効化しなければなりません。

しかし、「インデックスに含まれる列は更新せず、それ以外の列だけを更新する」ケースはどうでしょうか?

HOT更新は、この状況を最大限に活用します。もしヒープ上の同じページ内に新しいタプルを格納する十分な空き容量があれば、PostgreSQLは「インデックスの更新をスキップ」します。新しいタプルは古いタプルのポインタ(リダイレクション)を保持し、インデックスは古いタプルを指したまま、HOTチェーンを辿って最新のデータに到達できるのです。

この仕組みによって得られるメリットは計り知れません。

  • インデックスの肥大化抑制: インデックスエントリの生成が抑えられるため、Vacuumの負荷が激減します。
  • 物理的なI/O削減: インデックスの書き込みが不要になるため、WALの生成量も抑えられ、スループットが劇的に改善します。

—

現場でHOT更新を「効かせる」ための境界線

理論を知るだけでなく、実戦でこの恩恵を享受するには、いくつか押さえておくべき「制約」があります。

1. `FILLFACTOR` の重要性

HOT更新が成功するための絶対条件は「同じページ内に新しいタプルを格納する空きがあること」です。もしテーブルの `FILLFACTOR` が100のままだと、少しの更新でページが満杯になり、HOT更新は即座に無効化されます。
特に更新頻度が高いテーブルであれば、`FILLFACTOR` を90や85に下げて、物理的な「余白」を作っておくのが、現場のセオリーです。

2. インデックス列の設計

「どの列をインデックスに含めるか」は、単なるクエリの高速化の話だけではありません。頻繁に更新される列をインデックスに含めてしまうと、その瞬間にHOT更新の道は絶たれます。
「この列は検索に使うが、頻繁に更新もされる」というジレンマに直面したときは、そのインデックスの有用性と、HOT更新が効かなくなることによるコスト増を天秤にかける必要があります。

—

パフォーマンストラブルシューティング:なぜHOTが効かないのか?

「設計は悪くないはずなのに、なぜかインデックスが肥大化している」。そんなときは、`pg_stat_user_tables` を覗いてみてください。

SELECT n_tup_upd, n_tup_hot_upd,
(n_tup_hot_upd::float / n_tup_upd) as hot_ratio
FROM pg_stat_user_tables
WHERE relname = ‘your_table_name’;

この `hot_ratio` が極端に低い場合、何かがHOT更新を阻害しています。チェックすべきは以下のポイントです。

  • インデックスの多用: 関係ない列にまでインデックスを張っていないか?
  • ページがパンパンではないか: 前述の `FILLFACTOR` の調整漏れです。
  • 更新頻度が高すぎる列: 特定のフラグ列などを頻繁に更新していないか?

特に厄介なのは、アプリケーション側で「更新の必要がないのに全カラムを `UPDATE` 文で投げている」ケースです。これではインデックス列が変更されていなくても、HOT更新の恩恵を受けられません。変更されたカラムだけを `UPDATE` する設計にするだけで、データベースの寿命は延びます。

—

最後に:データベースは「生き物」である

PostgreSQLというデータベースは、非常に賢い作りをしていますが、開発者がその特性を理解していないと、そのポテンシャルを半分も引き出せません。

HOT更新を意識したモデリングやチューニングは、単なる最適化の手法というよりは、「データベースの負荷を最小化する作法」です。皆さんのシステムで、HOT更新が正しく機能しているか、一度統計情報を確認してみてはいかがでしょうか。

インデックスの肥大化に頭を抱える夜が、少しでも減ることを願っています。また、深い技術の話でお会いしましょう。

コメント

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