9.6で導入された機能です。9.6での導入以降、メジャーバージョンアップごとに改善がなされ、対象となる処理は増加しています。今回のコラムではバージョン12でのパラレルクエリを前提に概説します。パラレルクエリとはパラレルクエリとは、クエリの実行を並列化することで複数のCPUを活用し、性能向上を図ることを目指す仕組みです。パラレルクエリは、大量のデータに対して集計/分析を行うような場合に効果が期待できます。近年のサーバは複数のCPUを搭載したものが一般的になっていますが、パラレルクエリでは単一のクエリでも複数のプロセスにわたって処理を並列化できるため、これらのCPUを有効活用することができます。PostgreSQLでは、スレッドではなくプロセス単位で並列実行を行います。本記事では並列実行のために起動されるプロセスをワーカー、ワーカーが並列処理した結果の集約など並列実行する部分以外も担うプロセスをリーダーと呼びます。パラレルクエリの使い方パラレルクエリ専用の構文はありません※。PostgreSQLが実行計画を立てる際に、パラレルクエリが最も効率的な方法であると判断した場合に、パラレルクエリが選択されます。アプリケーションレベルで処理を並列化しようとした場合、マルチプロセス/マルチスレッドで動作させることを意識して処理を記述する必要がありますが、パラレルクエリではユーザはそのような手間をかけることなく、並列処理の恩恵を受けることができます。※例外として、pg_hint_planという実行計画を制御するエクステンションを利用すると、クエリ中にヒントを指定することでパラレルクエリの実行有無や並列数にヒントを与えることができます。実行するクエリがパラレルクエリになるか調べるためには、実行計画を確認します。パラレルクエリを利用しない場合について見てみます。データはPostgreSQL同梱のベンチマークツールであるpgbenchのテーブルを利用します。--パラレルクエリを無効にする。max_parallel_workers_per_gatherについては後述。;pgbench_accountsテーブルをシーケンシャルスキャンし、その結果の最大値を計算しています。変わったところはないシンプルな実行計画です。続いて、パラレルクエリを利用してみましょう。0'などの出力があり、パラレルクエリ用のワーカーが起動していることが推測できるかと思います。(ア)、とそれぞれのプロセス単位での最大値を計算する部分(イ)です。その後この実行計画では、リーダーが2の結果を集めた(ウ)上で、全体としての最大値を計算(エ)しています。並列に実行されている1と2の処理には、リーダーも参加しています。今回の例ではワーカー2つに加えリーダー1つで並列実行されるため、実際の並列度は3になります※。※スキャンした行数をみると、リーダーが並列実行に参加していることがわかります。1は1,598,505なので、合計3,434,923ですが、pgbench_accountsテーブルの行数は5,000,000なので1,565,077行差異があります。この差分がリーダーがスキャンした行数になります。12では、以下の処理が並列実行可能です。INTO逆に以下のような操作はパラレルクエリとしては実行できないため、通常のクエリとして実行します。パラレルクエリ」を参照してください。(1)データを書き込んだり、行のロックを取得するクエリたとえばUPDATE文やDELETE文などはパラレルクエリとして実行できません。上のCREATE文、SELECT文は例外的にパラレルクエリとして実行できます。(2)クエリ実行中にサスペンドされる可能性のあるクエリたとえば、カーソルを使った操作や、PL/pgSQLのループはパラレルクエリとしては実行できません。関数は並列に実行可能かどうかが定義されています。proparallel列から確認できます。restricted。restrictedな処理なので、リーダーでは実行可能ですがワーカーでは実行できません。パラレルクエリが実行されるための条件パラレルクエリが実行できる処理でも、必ずパラレルクエリとなるわけではなりません。主な条件を列挙します。max_parallel_workers_per_gatherが1以上であること先程パラレルクエリの実行計画を確認した際に、(ウ)にGatherというノードが現れていました。Gatherより下の部分が並列に実行されるのですが、max_parallel_workers_per_gatherは1つのGatherに起動できる最大のワーカー数を設定します。max_parallel_workers_per_gatherを0に設定すると1つもワーカーを起動できなくなるため、1以上に設定する必要があります。冒頭のクエリではパラレルクエリを無効にした実行計画を確認するために、このパラメータを0に変更していました。パラレルクエリを含むワーカ一プロセス一般についてもmax_worker_processesというパラメータで上限がかけられています※。このため、これらのパラメータが1以上に設定されており、まだこれらのパラメータの上限に達していないことがパラレル化の必要条件となります。※パラレルクエリのワーカーは、バックグラウンドワーカーというPostgreSQLからユーザなどが提供するコードを別のプロセスで実行できる仕組みを利用しています。このバックグラウンドワーカーの起動できるプロセスの上限数を指定するのがmax_worker_processesです。(3)パラレルクエリを実行できるテーブルサイズであることあまりにも小さいテーブルに対してパラレルクエリを実行しても、相対的に処理の分割損が大きくなり、並列実行の恩恵を受けることが難しいと考えられます。min_prallel_table_scan_sizeというパラメータでパラレルクエリを実行できる最小のテーブルサイズを設定しており、この値より大きいテーブルサイズである必要があります。(4)パラレルクエリを実行するのが効率的であることPostgreSQLは実行計画を作成する際に、並列実行しない方法とコスト比較し、並列実行するのが最も効率が高いと見積もった場合にパラレルクエリを選択します。このコストを計算する基礎値を与えるパラメータにparallel_setup_costとparallel_tuple_costがあります。それぞれパラレルクエリを実行する初期コスト、パラレルワーカーから他のプロセスへ1行を渡すコストです。並列数の決定パラレルクエリを実行する場合、PostgreSQLは起動するワーカーの数をスキャンするテーブルの大きさを元に決定します。具体的にはテーブルの大きさが3倍になるとワーカー数が1増えます。実行するマシンのCPUコア数などは考慮しません。このため、大規模なテーブルをスキャンするクエリが複数ある場合などは、物理的なコア数以上にプロセスを起動してしまう可能性がありますが、この場合並列実行は性能向上に寄与しないでしょう。並列数を指定したい場合、テーブルのパラメータであるparallel_workersを変更します。※前述のとおりpg_hint_planを利用している場合、クエリ中のヒントでテーブルの並列度を指定することが可能です。以下の例では、PostgreSQLがテーブルの大きさからワーカー数を4としているクエリについて、parallel_workersを変更することでワーカー数を5に変更しています。PostgreSQLにワーカー数を決めさせてみます。3まで起動されており、合計4つのワーカーが起動したことが確認できます。loops=1続いて、parallel_workersを指定してみます。4まで起動されており、合計5つのワーカーが起動したことが確認できます。msなお、パラレル数を2倍にしても一般に性能は2倍になりません。これは並列化できない部分の存在や分割によるオーバーヘッド増加などによるものです。このため、過度に並列数を増やしても、通常あまり効果は期待できないです。テーブルの大きさが3倍になると1ワーカーを増やすというPostgreSQLの方針は、テーブルが大きくなってもあまり並列数を上げないことになるため、この並列処理の性質と適合しています。今回は、PostgreSQLのパラレルクエリの概要から対象となる処理、実際にパラレルクエリが実行されるための条件や並列数の決め方について概説しました。うまくパラレルクエリが動作した場合、性能が劇的に改善することも少なくないので、性能改善の手段の1つとして押さえておくとよいと思います。淳(著者)2008年頃からオープンソースソフトウェアの技術調査や案件導入に従事。第4版』(翔泳社)がある。メリット受験対策インタビューFAQ資料請求・お問い合わせプライバシーポリシーこの内容で送信します。よろしいですか?キャンセル。