Postgresを遅くする方法
(byteofdev.com)- Postgresの性能を極端に低下させられるパラメータの組み合わせに関する実験的アプローチの紹介
- 一般的には キャッシュ、インデックス、WAL、I/O などさまざまな要素を逆方向にチューニング
- shared_buffers、autovacuum、WAL 関連オプションを極端に操作し、TPS を 42,000 倍低下させることに成功
- 新しい Postgres 18/19 バージョンの io_method および io_workers など最新機能も適用し、単一 I/O スレッド制限の実験を実施
- 実験の結果、Postgres の設定ファイルだけでも極端な性能低下が可能であることを実証
概要
この記事は、通常は高速化に注力する Postgres チューニングとは逆に、ひたすら 遅くすること だけを目的として、さまざまな PostgreSQL の設定値だけを変更し、性能を限界まで低下させた実験内容です。
テストは BenchBase の TPC-C ワークロード(128 倉庫、100 コネクション、それぞれ最大 10,000 トランザクション/秒を試行、最新の Postgres 19devel、Ryzen 7950x、32GB RAM、2TB SSD 環境、120 秒実行)に基づいています。
デフォルト値での性能は 7082 TPS であり、各パラメータ操作によってどれほど遅くなるかを段階的に観察しています。
キャッシュを大幅に減らす
- Postgres は disk I/O を減らすための強力なキャッシュ(shared_buffers) を活用します
- デフォルト値(10GB)から shared_buffers を 8MB に減少させると、TPS は 1/7 程度(1052 TPS)まで低下
- cache hit 比率が 99.90% から 70.52% に低下し、read syscall が 300 倍以上増加する現象を観測
- 128kB まで減らそうとしましたが、Postgres は最小でも約 2MB までしか許容せず、485 TPS までさらに低下
バックグラウンド処理を増やす(autovacuum チューニング)
- autovacuum 関連のすべての閾値を最小化し、ほぼ毎回の処理で vacuum が動作するように設定
- autovacuum_vacuum_insert_threshold=1、autovacuum_naptime=1 などの組み合わせ
- vacuum が実質的に仕事のない状態でも、ほぼ 1 秒ごとに繰り返し動作
- この過程で maintenance_work_mem を 128kB に縮小し、すべての autovacuum ログを有効化
- その結果、TPS は 293 に減少(元と比べて 1/20 以下)
- autovacuum 関連のリアルタイムログを通じて、実際に頻繁なバックグラウンド処理が性能低下の原因であることを確認
WAL(Write-Ahead Log)書き込み処理を最悪化
- WAL 関連パラメータをすべて最悪になるよう調整
- wal_writer_flush_after=0、wal_writer_delay=1、wal_sync_method=open_datasync など
- checkpoint を 30 秒ごとに強制し、min/max_wal_size=32MB で最小限に維持
- wal_level=logical、wal_log_hints=on など、WAL に不要な情報まで記録
- track_wal_io_timing、summarize_wal など追加負荷も有効化
- その結果 TPS は 98 まで減少(元と比べて 1/70 以下)
- ログでは checkpoints が数百 ms ごとに繰り返されるなど、異常な動作を確認
インデックス効果をなくす
- インデックス使用がすべて コスト最大として計算される値(random_page_cost=1e300、cpu_index_tuple_cost=1e300)に設定し、実質的にインデックスを無効化
- shared_buffers を 8MB まで増やし(安定性確保用)、TPS は 0.87 まで低下(7000 倍遅い状態を達成)
I/O を単一スレッドに強制
- 最新の Postgres 18+ 機能を活用
- io_method=worker、io_workers=1 として すべての I/O を単一ワーカースレッドに強制
- TPS は 0.016 までさらに低下(42,000 倍遅い)
- 100 コネクション、120 秒の実験で、成功したトランザクションは 11 件だけというほど制限された性能
結論と再現案内
- 合計 32 種類のパラメータ操作だけで、本番 DB を事実上「麻痺」状態にできることを実証
- postgresql.conf の設定だけを触って性能低下を極大化できる
- 実験を再現したいユーザーは、BenchBase Postgres、上記の TPC-C 環境、そして全設定一覧を参照
- 一部の追加パラメータや、さらに遅くする試みは含まれていません
要約パラメータ一覧
- shared_buffers = 8MB
- autovacuum 関連 thresholds/scale_factor = 0〜1 に最小化
- vacuum 関連のコストおよびメモリ/ログ: 最小化&最大化
- WAL 関連の sync/flush/ログ/レベルなど: 遅くなるよう維持
- インデックス関連 random_page_cost、cpu_index_tuple_cost: 1e300 を指定
- io_method = worker、io_workers = 1
- その他の詳細値は本文の一覧を参照
まとめ
- 単に postgresql.conf ファイルだけで深刻な性能低下を引き起こせる
- 実務ではこれらの組み合わせを逆方向に(効率的な性能改善に)参考にする価値がある
- 実験中、筆者の腰痛による中断に触れて記事を締めくくっている
2件のコメント
Hacker Newsのコメント
素晴らしいですね。こういうアプローチはとても好きです。