KEMBAR78
統計情報のリセットによるautovacuumへの影響について(第39回PostgreSQLアンカンファレンス@オンライン 発表資料) | PDF
© 2023 NTT DATA Corporation 1
第39回 PostgreSQLアンカンファレンス@オンライン
統計情報のリセットによるautovacuumへの影響について
2023年2月20日
株式会社NTTデータ 藤井 雅雄
© 2023 NTT DATA Corporation 2
自己紹介
藤井 雅雄
Database Technical Lead @ NTTデータ
データベース研究開発
PostgreSQL 技術支援
PostgreSQLコミッタ
レプリケーション
WAL圧縮
バックアップ進捗確認
pg_bigm(全文検索モジュール) コミッタ
fujii_masao
MasaoFujii
© 2023 NTT DATA Corporation 3
本講演について
講演資料は、後日、NTTデータのSlideShareアカウント上で公開予定です。
https://www.slideshare.net/nttdata-tech
© 2023 NTT DATA Corporation 4
統計情報のリセットによる
autovacuumへの影響について
© 2023 NTT DATA Corporation 5
統計情報のリセットによるautovacuumへの影響について、ドキュメントに警告が追記
2022年10月に、ドキュメントへの警告の追記がコミット
doc: warn pg_stat_reset() can cause vacuum/analyze problems
https://github.com/postgres/postgres/commit/4d070469c19f85043293789c570dbe8fb41ab1bb
ドキュメントには以下の警告が追記
Warning
Using pg_stat_reset() also resets counters that autovacuum
uses to determine when to trigger a vacuum or an analyze.
Resetting these counters can cause autovacuum to not perform
necessary work, which can cause problems such as table bloat
or out-dated table statistics. A database-wide ANALYZE is
recommended after the statistics have been reset.
https://www.postgresql.org/docs/devel/monitoring-stats.html#MONITORING-STATS-FUNCTIONS
意訳すると、
• 統計情報がリセットされると、autovacuumが必要なVACUUMや
ANALYZEを実行できない(実行が必要と判断できない)ことがある。
• この問題を解消するには、DB全体にANALYZEを実行して統計情報を
アップデートすることが推奨される。
© 2023 NTT DATA Corporation 6
autovacuumによるVACUUMとANALYZEの必要性判断
autovacuumは、以下の条件いずれかを満たすテーブルについてVACUUMが必要と判断
pg_stat_all_tables.n_dead_tup >
autovacuum_vacuum_threshold
+ autovacuum_vacuum_scale_factor * pg_class.reltuples
autovacuum_vacuum_insert_threshold >= 0 &&
pg_stat_all_tables.n_ins_since_vacuum >
autovacuum_vacuum_insert_threshold
+ autovacuum_vacuum_insert_scale_factor * pg_class.reltuples
autovacuumは、以下の条件を満たすテーブルについてANALYZEが必要と判断
pg_stat_all_tables.n_mod_since_analyze >
autovacuum_analyze_threshold
+ autovacuum_analyze_scale_factor * pg_class.reltuples
ゴミレコード数が指定の閾値より多いテーブルには、
(ゴミ回収のため)VACUUMが必要と判断
前回のVACUUM以降に挿入されたレコード件数
が指定の閾値より多いテーブルには、(インデック
スオンリイースキャンを効かせるため)VACUUMが
必要と判断
前回のANALYZE以降に挿入・更新・削除されたレコー
ド件数が指定の閾値より多いテーブルには、(プランナ統
計情報の最新化のため)ANALYZEが必要と判断
© 2023 NTT DATA Corporation 7
0
統計情報がリセットされると、
autovacuumは、以下の条件いずれかを満たすテーブルについてVACUUMが必要と判断
pg_stat_all_tables.n_dead_tup >
autovacuum_vacuum_threshold
+ autovacuum_vacuum_scale_factor * pg_class.reltuples
autovacuum_vacuum_insert_threshold >= 0 &&
pg_stat_all_tables.n_ins_since_vacuum >
autovacuum_vacuum_insert_threshold
+ autovacuum_vacuum_insert_scale_factor * pg_class.reltuples
autovacuumは、以下の条件を満たすテーブルについてANALYZEが必要と判断
pg_stat_all_tables.n_mod_since_analyze >
autovacuum_analyze_threshold
+ autovacuum_analyze_scale_factor * pg_class.reltuples
不等式左辺の統計情報の値が0にリセットされ、
一方で、右辺はパラメータやカタログ情報
(pg_class.reltuples)のためリセットされな
いことから、不等式が成り立たず、
autovacuumはVACUUMやANALYZEを
不要と判断する。
リセット以降に統計情報の値が0からカウント
アップされていき、指定の閾値より多くなったら、
autovacuumはVACUUMやANALYZEを
必要と判断する。
0
0
不等式左辺の統計情報の値
>
>
>
© 2023 NTT DATA Corporation 8
autovacuumがVACUUM実行する例
=# CREATE TABLE test AS SELECT n i, n j FROM generate_series(1, 100000) n;
=# VACUUM ANALYZE test;
=# ALTER TABLE test SET (log_autovacuum_min_duration = 0);
=# SELECT current_setting('autovacuum_vacuum_threshold')::numeric +
current_setting('autovacuum_vacuum_scale_factor')::numeric * reltuples threshold
FROM pg_class WHERE relname = 'test';
threshold
-----------
20050
(1 row)
=# UPDATE test SET j = j + 1 WHERE i <= 20051;
LOG: automatic vacuum of table "postgres.public.test": index scans: 0
pages: 0 removed, 532 remain, 179 scanned (33.65% of total)
tuples: 20051 removed, 99906 remain, 0 are dead but not yet removable
removable cutoff: 750, which was 0 XIDs old when operation ended
....
閾値より多いレコードをUPDATEして、
その分のゴミレコードを生成すると、
autovacuumがVACUUMを実行して、
そのログが出力される
autovacuumがVACUUMを必要と判断する
ゴミレコード数の閾値を計算
レコード数10万件のテーブルを作成して、
autovacuumが走ったらログ出力するように設定
© 2023 NTT DATA Corporation 9
統計情報リセットによりautovacuumがVACUUM実行しない例
UPDATE test SET j = j + 1 WHERE i BETWEEN 1 AND 10000;
SELECT pg_stat_reset();
UPDATE test SET j = j + 1 WHERE i BETWEEN 10001 AND 20000;
SELECT pg_stat_reset();
UPDATE test SET j = j + 1 WHERE i BETWEEN 20001 AND 30000;
SELECT pg_stat_reset();
UPDATE test SET j = j + 1 WHERE i BETWEEN 30001 AND 40000;
SELECT pg_stat_reset();
UPDATE test SET j = j + 1 WHERE i BETWEEN 40001 AND 50000;
.... (autovacuumのログが出力されない)
ゴミレコード数が閾値を超過しないように、
統計情報のリセットを挟みながらUPDATEすると、
閾値より大幅に多いレコードをUPDATEして
その分のゴミレコードが発生しても、
autovacuumはVACUUM実行しない
(そのautovacuumのログは出力されない)
© 2023 NTT DATA Corporation 10
統計情報のリセットの契機
① pg_stat_reset()の実行
② リカバリ (クラッシュリカバリ及びアーカイブリカバリ) の実行
③ レプリケーションのスタンバイの初期起動
 初期起動によりスタンバイ側の統計情報はリセットされる。以降のスタンバイ動作中、スタンバイ上でのクエリ実行
により統計情報の一部(スキャン件数など)は更新されるが、autovacuumが使うpg_stat_all_tablesの
n_dead_tupやn_ins_since_vacuum、n_mod_since_analyzeは0のまま(統計情報がプライマリ側
からレプリケーションされることもない)
 レプリケーションによる高可用構成において、フェイルオーバなどでスタンバイがプライマリに昇格すると、
autovacuumが使うカラムが0のままとなり、VACUUMやANALYZEの必要性判断を正しく行えない可能性が
ある
© 2023 NTT DATA Corporation 11
統計情報のリセットによるautovacuumへの影響が疑われる場合
PostgreSQLドキュメントでは、DB全体へのANALYZE実行が推奨されている。
A database-wide ANALYZE is recommended after the statistics have been reset.
https://www.postgresql.org/docs/devel/monitoring-stats.html#MONITORING-STATS-FUNCTIONS
➡ ANALYZE実行により統計情報のpg_stat_all_tables.n_dead_tupが更新されて、
autovacuumは適切にVACUUMの必要性を判断できるようになる
pg_stat_all_tables.n_dead_tup >
autovacuum_vacuum_threshold
+ autovacuum_vacuum_scale_factor * pg_class.reltuples
➡ ANALYZE実行では統計情報のpg_stat_all_tables.n_ins_since_vacuumは更新されないため、
レコード挿入件数に応じたVACUUMが統計情報リセットにより不足していると想定される場合は、
個別にVACUUMを実行する必要がある
autovacuum_vacuum_insert_threshold >= 0 &&
pg_stat_all_tables.n_ins_since_vacuum >
autovacuum_vacuum_insert_threshold
+ autovacuum_vacuum_insert_scale_factor * pg_class.reltuples
© 2023 NTT DATA Corporation 12
統計情報のリセットによるautovacuumへの影響が疑われる場合
PostgreSQLドキュメントでは、DB全体へのANALYZE実行が推奨されている。
A database-wide ANALYZE is recommended after the statistics have been reset.
https://www.postgresql.org/docs/devel/monitoring-stats.html#MONITORING-STATS-FUNCTIONS
➡ ANALYZE実行では統計情報のpg_stat_all_tables.n_mod_since_analyzeは更新されないが、
そもそもANALYZEが実行されるため、ANALYZE不足の可能性は解消される
pg_stat_all_tables.n_mod_since_analyze >
autovacuum_analyze_threshold
+ autovacuum_analyze_scale_factor * pg_class.reltuples
© 2023 NTT DATA Corporation 13
個人的には、
必要に応じて自分たちでVACUUMとANALYZEを
定期実行する仕組みを検討する。
autovacuumに任せきりにしない。
統計情報のリセット後に、
DB全体にANALYZEを実行する
統計情報のリセット後に、
該当のテーブルに対してのみ
ANALYZEを実行する
pg_statsinfoなどでゴミレコードの状況を監視して、その監視結果に応じてVACUUMやANALYZEを実行する
統計情報が
頻繁にリセットされる?
統計情報のリセット後に
DB全体にANALYZEを
実行できる"余裕"がある?
VACUUMやANALYZEの
実行が少しでも遅れることが
許されないテーブルがある?
統計情報が頻繁にリセットされる状況でなければ、リカバリやフェイルオーバの後にVACUUMとANALYZEが
閾値の2倍分だけ実行が遅れる程度の影響なので、そこまで問題視する必要はないかもしれない??
フローチャート的に対応を検討すると、
Yes
Yes
Yes
No
No
No
© 2023 NTT DATA Corporation 14
その他、記載されている会社名、商品名、又はサービス名は、
各社の登録商標又は商標です。

統計情報のリセットによるautovacuumへの影響について(第39回PostgreSQLアンカンファレンス@オンライン 発表資料)

  • 1.
    © 2023 NTTDATA Corporation 1 第39回 PostgreSQLアンカンファレンス@オンライン 統計情報のリセットによるautovacuumへの影響について 2023年2月20日 株式会社NTTデータ 藤井 雅雄
  • 2.
    © 2023 NTTDATA Corporation 2 自己紹介 藤井 雅雄 Database Technical Lead @ NTTデータ データベース研究開発 PostgreSQL 技術支援 PostgreSQLコミッタ レプリケーション WAL圧縮 バックアップ進捗確認 pg_bigm(全文検索モジュール) コミッタ fujii_masao MasaoFujii
  • 3.
    © 2023 NTTDATA Corporation 3 本講演について 講演資料は、後日、NTTデータのSlideShareアカウント上で公開予定です。 https://www.slideshare.net/nttdata-tech
  • 4.
    © 2023 NTTDATA Corporation 4 統計情報のリセットによる autovacuumへの影響について
  • 5.
    © 2023 NTTDATA Corporation 5 統計情報のリセットによるautovacuumへの影響について、ドキュメントに警告が追記 2022年10月に、ドキュメントへの警告の追記がコミット doc: warn pg_stat_reset() can cause vacuum/analyze problems https://github.com/postgres/postgres/commit/4d070469c19f85043293789c570dbe8fb41ab1bb ドキュメントには以下の警告が追記 Warning Using pg_stat_reset() also resets counters that autovacuum uses to determine when to trigger a vacuum or an analyze. Resetting these counters can cause autovacuum to not perform necessary work, which can cause problems such as table bloat or out-dated table statistics. A database-wide ANALYZE is recommended after the statistics have been reset. https://www.postgresql.org/docs/devel/monitoring-stats.html#MONITORING-STATS-FUNCTIONS 意訳すると、 • 統計情報がリセットされると、autovacuumが必要なVACUUMや ANALYZEを実行できない(実行が必要と判断できない)ことがある。 • この問題を解消するには、DB全体にANALYZEを実行して統計情報を アップデートすることが推奨される。
  • 6.
    © 2023 NTTDATA Corporation 6 autovacuumによるVACUUMとANALYZEの必要性判断 autovacuumは、以下の条件いずれかを満たすテーブルについてVACUUMが必要と判断 pg_stat_all_tables.n_dead_tup > autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor * pg_class.reltuples autovacuum_vacuum_insert_threshold >= 0 && pg_stat_all_tables.n_ins_since_vacuum > autovacuum_vacuum_insert_threshold + autovacuum_vacuum_insert_scale_factor * pg_class.reltuples autovacuumは、以下の条件を満たすテーブルについてANALYZEが必要と判断 pg_stat_all_tables.n_mod_since_analyze > autovacuum_analyze_threshold + autovacuum_analyze_scale_factor * pg_class.reltuples ゴミレコード数が指定の閾値より多いテーブルには、 (ゴミ回収のため)VACUUMが必要と判断 前回のVACUUM以降に挿入されたレコード件数 が指定の閾値より多いテーブルには、(インデック スオンリイースキャンを効かせるため)VACUUMが 必要と判断 前回のANALYZE以降に挿入・更新・削除されたレコー ド件数が指定の閾値より多いテーブルには、(プランナ統 計情報の最新化のため)ANALYZEが必要と判断
  • 7.
    © 2023 NTTDATA Corporation 7 0 統計情報がリセットされると、 autovacuumは、以下の条件いずれかを満たすテーブルについてVACUUMが必要と判断 pg_stat_all_tables.n_dead_tup > autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor * pg_class.reltuples autovacuum_vacuum_insert_threshold >= 0 && pg_stat_all_tables.n_ins_since_vacuum > autovacuum_vacuum_insert_threshold + autovacuum_vacuum_insert_scale_factor * pg_class.reltuples autovacuumは、以下の条件を満たすテーブルについてANALYZEが必要と判断 pg_stat_all_tables.n_mod_since_analyze > autovacuum_analyze_threshold + autovacuum_analyze_scale_factor * pg_class.reltuples 不等式左辺の統計情報の値が0にリセットされ、 一方で、右辺はパラメータやカタログ情報 (pg_class.reltuples)のためリセットされな いことから、不等式が成り立たず、 autovacuumはVACUUMやANALYZEを 不要と判断する。 リセット以降に統計情報の値が0からカウント アップされていき、指定の閾値より多くなったら、 autovacuumはVACUUMやANALYZEを 必要と判断する。 0 0 不等式左辺の統計情報の値 > > >
  • 8.
    © 2023 NTTDATA Corporation 8 autovacuumがVACUUM実行する例 =# CREATE TABLE test AS SELECT n i, n j FROM generate_series(1, 100000) n; =# VACUUM ANALYZE test; =# ALTER TABLE test SET (log_autovacuum_min_duration = 0); =# SELECT current_setting('autovacuum_vacuum_threshold')::numeric + current_setting('autovacuum_vacuum_scale_factor')::numeric * reltuples threshold FROM pg_class WHERE relname = 'test'; threshold ----------- 20050 (1 row) =# UPDATE test SET j = j + 1 WHERE i <= 20051; LOG: automatic vacuum of table "postgres.public.test": index scans: 0 pages: 0 removed, 532 remain, 179 scanned (33.65% of total) tuples: 20051 removed, 99906 remain, 0 are dead but not yet removable removable cutoff: 750, which was 0 XIDs old when operation ended .... 閾値より多いレコードをUPDATEして、 その分のゴミレコードを生成すると、 autovacuumがVACUUMを実行して、 そのログが出力される autovacuumがVACUUMを必要と判断する ゴミレコード数の閾値を計算 レコード数10万件のテーブルを作成して、 autovacuumが走ったらログ出力するように設定
  • 9.
    © 2023 NTTDATA Corporation 9 統計情報リセットによりautovacuumがVACUUM実行しない例 UPDATE test SET j = j + 1 WHERE i BETWEEN 1 AND 10000; SELECT pg_stat_reset(); UPDATE test SET j = j + 1 WHERE i BETWEEN 10001 AND 20000; SELECT pg_stat_reset(); UPDATE test SET j = j + 1 WHERE i BETWEEN 20001 AND 30000; SELECT pg_stat_reset(); UPDATE test SET j = j + 1 WHERE i BETWEEN 30001 AND 40000; SELECT pg_stat_reset(); UPDATE test SET j = j + 1 WHERE i BETWEEN 40001 AND 50000; .... (autovacuumのログが出力されない) ゴミレコード数が閾値を超過しないように、 統計情報のリセットを挟みながらUPDATEすると、 閾値より大幅に多いレコードをUPDATEして その分のゴミレコードが発生しても、 autovacuumはVACUUM実行しない (そのautovacuumのログは出力されない)
  • 10.
    © 2023 NTTDATA Corporation 10 統計情報のリセットの契機 ① pg_stat_reset()の実行 ② リカバリ (クラッシュリカバリ及びアーカイブリカバリ) の実行 ③ レプリケーションのスタンバイの初期起動  初期起動によりスタンバイ側の統計情報はリセットされる。以降のスタンバイ動作中、スタンバイ上でのクエリ実行 により統計情報の一部(スキャン件数など)は更新されるが、autovacuumが使うpg_stat_all_tablesの n_dead_tupやn_ins_since_vacuum、n_mod_since_analyzeは0のまま(統計情報がプライマリ側 からレプリケーションされることもない)  レプリケーションによる高可用構成において、フェイルオーバなどでスタンバイがプライマリに昇格すると、 autovacuumが使うカラムが0のままとなり、VACUUMやANALYZEの必要性判断を正しく行えない可能性が ある
  • 11.
    © 2023 NTTDATA Corporation 11 統計情報のリセットによるautovacuumへの影響が疑われる場合 PostgreSQLドキュメントでは、DB全体へのANALYZE実行が推奨されている。 A database-wide ANALYZE is recommended after the statistics have been reset. https://www.postgresql.org/docs/devel/monitoring-stats.html#MONITORING-STATS-FUNCTIONS ➡ ANALYZE実行により統計情報のpg_stat_all_tables.n_dead_tupが更新されて、 autovacuumは適切にVACUUMの必要性を判断できるようになる pg_stat_all_tables.n_dead_tup > autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor * pg_class.reltuples ➡ ANALYZE実行では統計情報のpg_stat_all_tables.n_ins_since_vacuumは更新されないため、 レコード挿入件数に応じたVACUUMが統計情報リセットにより不足していると想定される場合は、 個別にVACUUMを実行する必要がある autovacuum_vacuum_insert_threshold >= 0 && pg_stat_all_tables.n_ins_since_vacuum > autovacuum_vacuum_insert_threshold + autovacuum_vacuum_insert_scale_factor * pg_class.reltuples
  • 12.
    © 2023 NTTDATA Corporation 12 統計情報のリセットによるautovacuumへの影響が疑われる場合 PostgreSQLドキュメントでは、DB全体へのANALYZE実行が推奨されている。 A database-wide ANALYZE is recommended after the statistics have been reset. https://www.postgresql.org/docs/devel/monitoring-stats.html#MONITORING-STATS-FUNCTIONS ➡ ANALYZE実行では統計情報のpg_stat_all_tables.n_mod_since_analyzeは更新されないが、 そもそもANALYZEが実行されるため、ANALYZE不足の可能性は解消される pg_stat_all_tables.n_mod_since_analyze > autovacuum_analyze_threshold + autovacuum_analyze_scale_factor * pg_class.reltuples
  • 13.
    © 2023 NTTDATA Corporation 13 個人的には、 必要に応じて自分たちでVACUUMとANALYZEを 定期実行する仕組みを検討する。 autovacuumに任せきりにしない。 統計情報のリセット後に、 DB全体にANALYZEを実行する 統計情報のリセット後に、 該当のテーブルに対してのみ ANALYZEを実行する pg_statsinfoなどでゴミレコードの状況を監視して、その監視結果に応じてVACUUMやANALYZEを実行する 統計情報が 頻繁にリセットされる? 統計情報のリセット後に DB全体にANALYZEを 実行できる"余裕"がある? VACUUMやANALYZEの 実行が少しでも遅れることが 許されないテーブルがある? 統計情報が頻繁にリセットされる状況でなければ、リカバリやフェイルオーバの後にVACUUMとANALYZEが 閾値の2倍分だけ実行が遅れる程度の影響なので、そこまで問題視する必要はないかもしれない?? フローチャート的に対応を検討すると、 Yes Yes Yes No No No
  • 14.
    © 2023 NTTDATA Corporation 14 その他、記載されている会社名、商品名、又はサービス名は、 各社の登録商標又は商標です。