【実務・中級編】 並列クエリのアーキテクチャ – PostgreSQL

PostgreSQLの並列クエリ、その「舞台裏」を覗いてみよう

やあ。最近、PostgreSQLのパフォーマンスチューニングで悩んでいないかな?

大規模なデータセットを扱うとき、クエリが1つのCPUコアだけで必死に頑張っているのを見て、「もっと効率よくできないのか?」ともどかしくなることはよくあるよね。そんなとき、PostgreSQLの「並列クエリ(Parallel Query)」という強力な武器を使いこなせているかどうかで、システムのレスポンスは劇的に変わる。

今日は、PostgreSQLが裏側でどうやって並列処理を組み立てているのか、その心臓部である`Gather`ノードやバックグラウンドワーカーの仕組みを、少し「中の人」の視点で掘り下げてみよう。

—

並列クエリの指揮官:「Gather」と「Gather Merge」

まずは実行計画を見ていてよく目にする`Gather`と`Gather Merge`について整理しておこう。これらは、言わば「散らばった作業を1つにまとめる指揮官」だ。

Gather:とにかく集める

`Gather`ノードは、複数のバックグラウンドワーカーが個別に実行した結果を、1つのプロセスに吸い上げる役割を担う。
例えば、単純なテーブルスキャンを並列で行ったとき、各ワーカーが読んできたデータ断片を、親プロセスが「はい、こっちへ寄せて」とまとめてクライアントに返すイメージだね。順序を気にしないなら、これが一番効率がいい。

Gather Merge:順序を維持して集める

一方で`Gather Merge`は、もう少し賢い。もしクエリが`ORDER BY`を伴っているなら、各ワーカーが個別にソートした結果を、マージソートの要領で「順序を保ったまま」統合するんだ。これがあるおかげで、並列処理をした後でも結果がバラバラにならずに済むわけだ。

—

舞台裏の働き手:バックグラウンドワーカーの正体

次に、実際に手を動かす「バックグラウンドワーカー」についてだ。

PostgreSQLが並列処理を決定すると、クエリを実行するプロセス(リーダープロセス)は、設定された数の「バックグラウンドワーカー」をフォーク(生成)する。このワーカーたちは、リーダーと同じ実行計画の断片をそれぞれ担当する。

ここで大切なのが、「リーダープロセス自身も作業に参加する」という点だ。
よく「ワーカーを3つに設定したから、合計4つで処理する」という計算になるんだけど、現場ではここを計算に入れ忘れてリソースを食いつぶすケースをよく見る。

実践:並列度を意識したチューニング

例えば、こんな設定を意識したことはあるだろうか?

— テーブルの並列度を一時的に上げてみる
ALTER TABLE logs SET (parallel_workers = 4);

— クエリの実行計画を見てみる
EXPLAIN ANALYZE
SELECT count() FROM logs WHERE created_at > ‘2023-01-01’;

もし`EXPLAIN`の結果に`Parallel Seq Scan`が出ていなければ、それはPostgreSQLが「並列化するメリットがない」と判断している証拠だ。よくある原因はこれだ:

1. データが少なすぎる: 小さなテーブルなら、プロセスを立ち上げるオーバーヘッドの方が高くつくからね。
2. costのしきい値: `min_parallel_table_scan_size`の設定が、テーブルサイズより大きくなっていないか確認してみよう。
3. 関数が並列非対応: `PARALLEL SAFE`属性がついていない関数をクエリ内で使っていると、並列化は即座に無効になる。これは罠にはまりやすいポイントだよ。

—

現場のエンジニアへ:一つだけのアドバイス

並列クエリは魔法じゃない。むしろ「諸刃の剣」だ。

並列度を上げれば上げるほど、CPU負荷は跳ね上がるし、メモリ(`work_mem`)もワーカーの数だけ消費される。もし1つのクエリで全てのCPUコアを使い切ってしまったら、その間、他のユーザーのリクエストが待たされることになるよね。

だから、僕がアドバイスしたいのはこれだ。
「まずは『なぜ並列化されていないのか』の理由を探り、次に『並列化によってシステム全体の負荷が許容範囲か』を考えること。」

性能が出ないからといって、やみくもに`max_parallel_workers_per_gather`を大きくするのはNGだ。まずは`EXPLAIN`をじっくり眺めて、PostgreSQLがどこでボトルネックを感じているのか、対話するように読んでみてほしい。

—

PostgreSQLは、中身を理解すればするほど、実に理にかなった動きをしてくれる面白いデータベースだよ。もし、特定のクエリで「ここがどうしても並列化されない!」という悩みがあれば、またいつでも聞いてくれ。一緒に実行計画を紐解こう。

それじゃ、今日はこの辺で。ハッピー・チューニング!

コメント

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