【実務・中級編】 maintenance_work_mem – PostgreSQL

「遅い…」を解決する第一歩。PostgreSQLの `maintenance_work_mem` を使いこなそう

現場でPostgreSQLを触っていると、必ず一度は壁にぶつかるのが「メンテナンス処理の重さ」です。「インデックス作成に何時間もかかる」「VACUUMがちっとも終わらない」……そんな時、パラメータをいじって劇的に改善した経験、あなたにはありますか?

今日は、そんな現場の駆け込み寺的パラメータ、`maintenance_work_mem` について話をしましょう。教科書的な定義をなぞるだけじゃなく、「結局どう設定すればいいの?」という実践的な勘所を共有しますね。

—

`maintenance_work_mem` って、何者?

簡単に言うと、これは「メンテナンス作業専用の作業用メモリ」です。

PostgreSQLは、データ読み書き用のメモリ(`shared_buffers`など)とは別に、インデックスの作成(`CREATE INDEX`)や、`VACUUM`、`ALTER TABLE`といった「裏方の仕事」のためにメモリを確保します。その上限を決めているのがこの設定です。

デフォルト値は64MB。正直に言います。今の時代、この設定のまま運用していると、DBのポテンシャルをかなり殺している可能性が高いです。

なぜこのメモリが重要なのか

インデックス作成時を例に考えてみましょう。PostgreSQLはデータを並べ替えてインデックスを作るわけですが、この時メモリが足りないとどうなるか。

1. メモリに収まらない分をディスク(一時ファイル)に書き出す。
2. ディスクから読み直して再計算する。
3. また書き出す……。

……想像するだけで遅そうですよね。ディスクI/Oはメモリの数千倍遅いです。`maintenance_work_mem` を十分に割り当てておけば、この「ディスクへの退避」を抑え込み、メモリ上で高速にインデックスを構築できるんです。

実践的な設定の勘所

じゃあ、どれくらい設定すればいいの? という話ですよね。

結論から言うと、「システムに余裕があるなら、1GB〜数GB程度まで大胆に振る」のが僕の推奨です。

ただ、注意点がひとつ。この設定は「セッションごとに割り当てられる」という点です。もし同時に複数のインデックス作成コマンドを走らせるなら、その数だけメモリを食います。

設定を確認・変更するコマンド

まずは現在の値を見てみましょう。

SHOW maintenance_work_mem;

変更は、本番環境なら `postgresql.conf` を書き換えて再読み込み(`pg_ctl reload`)するのが基本ですね。

— 一時的に特定のセッションだけで大きくしたい場合(インデックス作成直前など)
SET maintenance_work_mem = ‘2GB’;
CREATE INDEX CONCURRENTLY idx_huge_table_col ON huge_table(column_name);

注意!「魔法の杖」ではない

ここで一つ、現場の先輩として釘を刺しておきたいことがあります。「大きくすればするほど速くなるわけではない」ということです。

ある一定のラインを超えると、それ以上メモリを積んでも劇的な効果は現れなくなります。また、サーバー全体の空きメモリがカツカツの状態でこれを大きくしすぎると、OSがメモリ不足(OOM Killer)を起こしてPostgreSQLごと落とされてしまう……なんて笑えない事故も起こり得ます。

  • 小〜中規模DBなら: 256MB〜512MB
  • 大規模かつメモリ潤沢なサーバーなら: 1GB〜4GB程度

まずはこのあたりから始めて、`EXPLAIN ANALYZE` や `pg_stat_statements` で処理時間を見て調整していくのが王道です。

まとめ:現場で意識してほしいこと

`maintenance_work_mem` は、いわば「DBの大掃除を快適にするための体力」です。

  • `CREATE INDEX` が遅いと感じたら、まずこの値を疑うこと。
  • 大量の `VACUUM` が走る夜間バッチがあるなら、その時だけ値を大きくする工夫を検討すること。
  • サーバーのメモリ総量と、同時実行数を忘れないこと。

インデックス作成の数時間が数分に短縮されたとき、その爽快感はエンジニア冥利に尽きるはずです。ぜひ、自分の環境でチューニングを試してみてください。

何か分からないことがあれば、またいつでも聞きに来てくださいね。現場からは以上です!

コメント

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