🙆

PostgreSQLのvacuumって何?

2025/02/13に公開

Daily Blogging 54日目

DBのこと一生わかるようになる気がしない

pgheroをシステムに導入したけど、vacuumっていう項目あって何それ?ってなった

削除してるようで削除してない

PostgreSQLって、実はDELETEクエリを実行したときに即座にレコードを削除しているわけじゃない。
対象のレコードに削除マークを付与することで削除扱いにしている。
この削除マークが付与されたレコードをデッドタプルと呼ぶらしい
デッドタプルとなった部分はDBの不要領域とされる

UPDATEクエリも実は同じ挙動をする。
レコードを更新するときは、その行自体を更新するわけじゃなくて、

  1. 対象レコードに削除マークを付与して
  2. 新しいレコードを挿入している

このようにレコードを追記していくやつを追記型アーキテクチャと呼ぶ

DBの掃除屋vacuum

デッドタプルを発生させっぱなしにしておくとストレージをめちゃくちゃ圧迫しちゃう
特にDELETE, UPDATEが多いテーブルはテーブルファイルが肥大化しやすい
そんな時に活躍するのはvacuum
こいつがデッドタプルを回収して、不要領域となった部分を再利用可能な状態に戻してくれる

3種類のvacuum

  • 通常のvacuum
    • デッドタプルを回収して、不要領域を開放する
      • その領域を再利用できるようになる
    • ファイルサイズはそのまま
  • vacuum full
    • デッドタプルを回収して、不要領域を含まない新しいテーブルファイルを作り直す
      • テーブルファイルのサイズがその分縮小
      • もともと使ってた不要なディスク領域は開放されてOS側で他の用途に使えるようになる
    • 実行中はテーブルロックが発生する
  • autovacuum
    • 定期的に通常のvacuumを実行する
    • デフォルトで有効化されている
    • テーブルに合わせて頻度の調整が必須

インデックスも一緒やで

インデックスファイルも追記型アーキテクチャなので、同じ現象が発生する。
元々値が格納されていた箇所が不要領域になるため、B-treeに効率的に格納できずにページが増えてインデックスファイルが肥大化する。
これをインデックスの断片化という
※ページとは、shared buffers上の1KB単位のブロックを指す
※インデックスファイルの値に削除フラグが付与されるわけではない

ページ数が増えることで、スキャンするページ数も増えるので検索効率が落ちる

こっちより

        [10, 20, 30]
       /      |      \
[1, X, 5, 9]   [X, 15, 19, 22]   [21, X, 28, 32]

こっちの方がファイルサイズも小さくて検索効率がいいみたいな

        [10, 20, 30]
       /      |      \
[1, 5, 9]   [15, 19, 22]   [21, 28, 32]

このインデックスの断片化を解消するのにもvacuumが使える。

他の解消法

vacuum以外にもインデックスの断片化を解消する方法がある

reindexコマンド

  • インデックス再構築
  • テーブルロックが発生する
REINDEX INDEX index_name;

pg_repackコマンド

  • インデックス再構築
  • テーブルロックなしで解消
SELECT pg_repack.repack_index('index_name');

まとめ

なんだかんだインデックスのメンテナンスってちゃんとやらないといけないんですねと

Discussion