「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` を叩いて、ワーカーがちゃんと働いているか、あるいは「働かなくていいところで無駄に起動しようとしていないか」を観察することから始めてみてほしい。
「なぜ並列化されたのか?」「なぜ並列化されなかったのか?」を論理的に説明できるようになったとき、君はもう一段階上のエンジニアになっているはずだ。
また何か詰まったら、いつでも聞いてくれよ。現場からは以上だ!
コメント