【実務・中級編】 パラレルワーカー – PostgreSQL

「PostgreSQLの並列処理」という名の魔法を解き明かす:パラレルワーカーの実践論

やあ。今日もクエリのチューニングと格闘しているかな?

PostgreSQLで重い分析クエリを投げたとき、「なぜかCPU使用率がスパイクして、一気に処理が終わる」という経験、あるよね。あれはPostgreSQLの「パラレルワーカー(Parallel Worker)」が裏で奔走してくれている証拠だ。

今日は、教科書的な説明はさらっと流して、実務でこの「並列処理」とどう付き合っていくべきか、現場の視点から深掘りしてみよう。

—

パラレルワーカーの正体:指揮官と現場の作業員

まずイメージしてほしい。君が巨大なテーブルの集計を命じたとする。PostgreSQLは、そのクエリを「リーダープロセス(君が接続しているバックエンド)」と、その配下の「パラレルワーカー(作業員)」で分担するんだ。

  • リーダープロセス: 指揮官。クエリを実行し、ワーカーを起動し、結果をまとめてクライアントに返す。
  • パラレルワーカー: 作業員。リーダーから「この範囲のデータを見ておいて」と指示を受け、スキャンや結合などの重い処理を並列で実行する。

ここで大切なのは、「ワーカーはあくまで作業員であり、結果の集約はリーダーの仕事である」ということ。ワーカーが多ければ多いほど速いわけじゃない。プロセス間通信(IPC)のコストやコンテキストスイッチのオーバーヘッドがあるから、最適解を見つけるのがエンジニアの腕の見せ所なんだ。

—

どんな時に「魔法」が発動するのか?

PostgreSQLは、主に以下のような「コストのかかる処理」でパラレルクエリを選択する。

  • Parallel Sequential Scan: 巨大なテーブルのフルスキャン。
  • Parallel Hash Join: 結合処理の高速化。
  • Parallel Aggregate: `GROUP BY` や `SUM` などの集計。

例えば、数千万件あるログテーブルから特定期間の平均値を出すようなクエリを投げると、PostgreSQLは賢いので勝手にワーカーを割り当ててくれる。

実践的なチェック方法

まずは、クエリの実行計画を見てみよう。

EXPLAIN ANALYZE
SELECT region, SUM(amount) FROM sales_table GROUP BY region;

もし結果に `Parallel Seq Scan` や `Gather` という言葉が出てきたら、それはパラレルクエリが動いている証拠だ。

Gather (cost=1000.00..12345.00 rows=100 width=12)
Workers Planned: 2
-> Parallel Seq Scan on sales_table (cost=0.00..10234.00 rows=50 width=12)

この「Workers Planned」が、PostgreSQLが「これくらいワーカーを動かしたら速いだろう」と見積もった数だ。

—

チューニングの現場:ハマりどころとコツ

「じゃあ、設定でワーカーを増やせば爆速になるのか?」というと、そうでもない。むしろ、設定を欲張りすぎるとDB全体が重くなる。現場でよく触るパラメータは以下の3つだ。

1. `max_parallel_workers_per_gather`:
一つのクエリで最大何個のワーカーを使うか。デフォルトは2だが、CPUコア数に余裕があるなら4〜8に増やすと劇的に変わることがある。
2. `max_parallel_workers`:
サーバー全体で起動していいワーカーの総数。これを高くしすぎると、他のクエリに影響が出る。
3. `min_parallel_table_scan_size`:
「これより小さいテーブルなら並列化する価値ないよね」という閾値。

アドバイス:
むやみにワーカーを増やすより、「そもそもインデックスは効いているか?」「統計情報は最新か?」を確認してほしい。パラレルクエリは、フルスキャンせざるを得ないような「重いクエリ」の最終手段なんだ。インデックスがあれば、そもそもワーカーを呼ぶ必要すらない。

—

注意点:ワーカーが動かない「あるある」

たまに「並列化してほしいのに動かない!」という相談を受ける。原因の多くはこれだ。

  • データ量が少ない: 小さなテーブルなら並列化のコストの方が高くつくため、PostgreSQLは賢く拒否する。
  • トランザクション分離レベル: `SERIALIZABLE` レベルでは、並列クエリが制限されることが多い。
  • 関数が不純(Volatile): ユーザー定義関数内でテーブルを書き換えるような処理があると、並列化できないことがある。

—

最後に:僕からのメッセージ

パラレルワーカーは、現代のPostgreSQLにおける強力な武器だ。でも、武器は使い手次第で宝にもゴミにもなる。

まずは `EXPLAIN` を叩いて、ワーカーがちゃんと働いているか、あるいは「働かなくていいところで無駄に起動しようとしていないか」を観察することから始めてみてほしい。

「なぜ並列化されたのか?」「なぜ並列化されなかったのか?」を論理的に説明できるようになったとき、君はもう一段階上のエンジニアになっているはずだ。

また何か詰まったら、いつでも聞いてくれよ。現場からは以上だ!

コメント

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