パフォーマンスチューニング9つの技 ~「探し」について~

今回は、実際の業務において押さえておきたいパフォーマンスチューニング手法の「探し」について解説します。ここでの「探し」とは、データベース内でアクセスすべきデータを効率的に絞り込んで探し出すことであり、時間がかかる処理や無駄な資源消費を排除することがテーマです。

探し

インデックスを有効活用する
  • ソート処理をインデックススキャンで代用する
  • 検索方式Index Only Scanを活用する
  • 複合インデックスは絞り込める順に記述する
  • OR条件を工夫する
  • 式インデックスを利用する
実行計画を評価し制御する
  • 実行計画を見る
  • 実行計画を制御する
  • 統計情報を固定化する
クライアント側で無駄を削減する
  • プリペアド文、コネクションプーリング、ユーザー定義関数を利用する
  • フェッチサイズを調整する

今回の記事は、パフォーマンスチューニングの観点と仕組みを理解することに主眼を置いています。具体的な対処方法についてはシステムによって異なるため、マニュアルの確認や、各種チューニングサービスのご利用をご検討ください。なお、この記事で対象にしているPostgreSQLのバージョンは9.5以降です。

本記事の構成

本記事「パフォーマンスチューニング9つの技」は以下4つの記事から構成されています。他の記事も併せてご覧ください。

1. パフォーマンスチューニングの「探し」とは

PostgreSQLは、SQLが発行されると、アクセス先のデータの特性を示す『統計情報』を参照し、一番効率の良いアクセス手順である『実行計画』を決定した上で、データベースへのアクセス処理を実行します。『実行計画』は、検索、結合、ソートなどの処理の階層的な組み合わせで構成されます。より効率的な『実行計画』が生成されるようにするためには、テーブルへの適切なインデックスを作成したり、SQL文の記述を工夫したりする必要があります。すると、アクセスするデータの範囲を効果的に絞り込まれてディスクI/Oが削減でき、また処理コストの低い手法で処理されるようになり、結果的にパフォーマンス向上につながります。図1に、今回説明するPostgreSQLのアーキテクチャー上の着目ポイントについて示します。

PostgreSQLの「探し」のポイント
図1 PostgreSQLの「探し」のポイント

PostgreSQL全体の構成や、サーバープロセスの処理(パーサー、リライター、プランナー、エグゼキューター)の説明は、「PostgreSQLのアーキテクチャー概要」を参照してください。

ここで、実際のパフォーマンスチューニングをする上での基礎知識として、インデックスを定義することによる効果と、プランナーが作成する実行計画の見かたについて説明します。

1.1 インデックス定義の効果について

インデックスが存在しないテーブルからデータを検索する場合、テーブルの先頭レコード(タプル)から順に全データにアクセスするため、処理に時間を費やします。

インデックスを利用しない場合のデータ検索
図2 インデックスを利用しない場合のデータ検索

テーブルにインデックスを定義した場合は、指定されたカラムのデータを基にソートした順でインデックスが作成され、それらのデータがテーブルのどこにあるのかを記憶します。必要なデータへアクセスする際には、インデックスを利用することで、ソートしたデータの中から該当のレコードを探せるため、アクセスしなければならないデータ量を減らし、検索処理を高速化することができます。

インデックスを利用した場合のデータ検索
図3 インデックスを利用した場合のデータ検索

ただし、高速化のためにインデックスを大量に定義し過ぎると、データ格納の際に大量のインデックスを更新しなければならないため、データ格納においてパフォーマンス劣化の問題が発生します。また、インデックス単体においても、インデックスのカラム数が多くなると更新時に時間を費やします。そのため、データ格納においてパフォーマンス問題が発生した場合は、インデックスに定義するカラムを必要最低限に減らすなどの検討も必要になるかもしれません。したがって、インデックス定義は、パフォーマンスを改善したいSQLで利用されているテーブルのカラムに対して優先的に行い、また複数のSQLから有効に利用できるようにするなど、インデックスを作り過ぎないことも検討してください。

例えば、カラムC1、C2、C3に対する条件を記述したSQLと、カラムC1、C2、C4に対する条件を記述したSQLがある場合、C1、C2、C3、C4のインデックスを作成し、両方のSQLでそのインデックスを利用することで高速に処理されるようになります。なお、カラムC3、C4のデータのばらつきが小さく(カーディナリティーが低い)、条件で絞り込みがほとんどできない場合は、C1、C2のインデックスのみを作成して両方のSQLで利用可能なインデックスを定義することで、データ格納時の速度も考慮した対策になります。

インデックスの定義例
図4 インデックスの定義例

インデックスを定義するかどうかの判断については、性能要件に基づいてパフォーマンスを満たしていないSQLがあれば、データ格納時におけるパフォーマンス劣化の問題を考慮しながらインデックスを定義していく必要があります。一般的にインデックスを定義したほうが良いテーブルは、以下のようなケースがあります。

  • テーブルのデータ量が多く、一部のレコードデータにのみアクセスする
  • カラムにおける値のばらつきが大きい(カーディナリティーが高い)

なお、これらに該当する場合でも、実際にWHERE句や結合条件としてほとんど使われないカラムへのインデックス定義や、データが頻繁に書き換わってインデックス更新がネックになるようなテーブルについては、インデックス利用が適さないことがあるため、十分に検討する必要があります。

1.2 プランナーが作成する実行計画の見かたについて

PostgreSQLがSQLを実行する処理において、大きくパフォーマンスに影響を与える機構がプランナーです。プランナーは、SQLが発行されると、定期的に実行されるautovacuumから呼び出されるANALYZE処理によって更新される「統計情報」を参照して、「実行計画(問い合わせ計画)」を作成します。「統計情報」には現在のテーブルにおけるデータ量やばらつきなどの統計的な情報が保持されており、プランナーは、この情報を参考にさまざまな検索方法や結合方法などの中から、処理コストが最小になる組み合わせを見つけ出し、「実行計画」を作成します。

実際にプランナーがどのような実行計画を作ったのかを知るためには、EXPLAINコマンドを使います。パラメーターにANALYZEを指定すると、実際にSQLを実行させ、その際の稼働時間を表示します。また、BUFFERSを指定すると、バッファーの使用状況に関する情報が表示されます。
以下に、SELECT文の実行計画の例を示します。

SELECT文の実行計画の例

はじめに、各ノードの1行目の情報の意味について示します。

ノードの種類の例

検索(スキャン)方法:Seq Scan / Index Scan / Index Only Scan / Bitmap Index Scan
結合方法:Nested Loop / Merge Join / Hash Join
その他:Sort / Hash / Aggregate / HashAggregate / Append / BitmapAnd / BitmapOr

プランナーが推定するコスト(最初の括弧)

cost=初期処理の推定コスト...全体推定コスト
rows=ノードが出力する行数(推定値)
width=ノードが出力する行の平均サイズ(推定値)(バイト単位)

実際の実行結果(次の括弧)

actual time=初期処理の実時間...全体の実時間(ミリ秒)
rows=実際に処理した行数
loops=ノードを実行した回数

次に、各ノードの処理に費やした時間について見てみます。

A)大きく木構造になっており、インデントで上下の関係を表しています。
この実行例では、上位ノード「Nested Loop」の下に、2つの下位ノード「Seq Scan」、「Index Scan」があります。
B)actual timeのそれぞれの値は、上位ノードは下位ノードの値も含めて計上されます。そのため、各ノード単位でかかるコストや時間は、下位ノードの値を差し引きする必要があります。
C)ノードがループして実行される場合は、loopsに実行された回数が記載され、括弧内に書かれているrows、actual timeにはその時の平均値が出力されます。なお、括弧外のBuffers部分などについては、平均値ではなく累計値で出力されます。また、並列処理についても並列度がloopsに含まれるため、並列処理の際には注意が必要です。
D)actual timeには、"最初の1行目を返却した時間..最後の行を返却した時間"の形式で出力されます(単位はミリ秒)。
E)各ノードの時間は、(actual timeの2つ目の値 × loops) - (下位のノードのactual timeの2つ目の値 × loops)で求められます。下位ノードが複数あれば、それらの値をすべてを差し引きます。並列処理の場合は、loopsの値に起動させたワーカー + 1となるため、並列で動作している分のloopsの掛け算は不要になります。

上記の実行計画について、ノードごとの処理時間をactual timeとloopsから計算すると以下のような結果になります。

ノードごとの処理時間の計算方法
図5 ノードごとの処理時間の計算方法

2. パフォーマンスチューニングの「探し」の技

ここからは、具体的なインデックスの活用例、最適な実行計画を生成する例、および、クライアント側でのSQLの書き方を工夫する方法について説明します。

2.1 インデックスを有効活用する

インデックスを活用しパフォーマンスを向上させるための手法を、いくつか紹介します。
ここでは以下の内容で説明します。

2.1.1 インデックス定義のより有効な活用方法

ソート処理(ORDER BY句)をインデックススキャンで代用する、LIMIT句がある場合はさらに有効

SELECT文にORDER BY句を使用する場合には、ORDER BY句に書かれているカラムの順番でインデックスが定義されていれば、SELECT文の実行時にソート処理が省略されます。それは、ソート処理を実行しなくてもインデックスを順番に見ていくことでソートされた結果を取り出すことができるためです。その結果、SELECT文は高速に処理できます。また、LIMIT句がある場合は、LIMITで指定された個数までしかデータにアクセスしないで済むため、さらに効果が見込めます。

ここで、例を挙げて、実際の動作を確認してみます。以下のように、テーブルtblと、カラムc1に対するインデックスのみを作成し、テストデータも作成します。

ソースコード1

まずは、以下のSQLのように、ORDER BY句のc2、c3にインデックスを利用しないケースを見てみます。

ソースコード2

実行計画を確認するため、EXPLAINコマンドにANALYZEオプションを指定して実行します。実行結果を見ると、インデックスはカラムc1にのみ定義されているため、【1】でc1 = 10のデータすべてを取り出し、【2】でc2とc3でソートし、【3】で最後にLIMITでレコード数を制限していることが分かります。

ソースコード3

これに対し、以下のようにc1、c2、c3カラムに複合インデックスを作成した上で先ほどと同じSQLを実行すると、ORDER BY句に指定されたc2、c3カラムを含むインデックスが定義されていることで、時間のかかるソート処理が動作せず、高速に実行されていることが確認できます。

ソースコード4

この理由について説明すると、まず、WHERE句にあるc1は等価条件(=)のためc1の検索するデータは1種類となり、インデックス検索を行うことで残りのc2、c3はソート順にデータが取り出せる状態になっています。そのため、ソート処理を実施しなくてもソートされた結果が取り出せることになります。また、すでにソートされたものを取り出しているため、LIMIT句の条件もさらに効果的に働きます。もともとは10,000件取り出してソートしてから500件に絞っていたものが、500件のデータを取り出すだけで済みます。
その結果、ソート処理が不要になり、かつ、アクセスするデータ量が減るため、高速化につながっています。

ソート処理をインデックススキャンで代用する例
図6 ソート処理をインデックススキャンで代用する例(LIMIT句も利用)

検索方式Index Only Scanを活用する

SELECT文で指定されたWHERE句と選択リストに指定されたカラムがすべてインデックスに含まれている場合、および、インデックスの種類がB-treeなどのようにIndex Only Scanをサポートしている場合には、プランナーが実行計画を作成する際に、高速なスキャン方式であるIndex Only Scanを選択します。Index Only Scanは、インデックスデータをアクセスするだけで処理ができ、テーブルデータへのアクセスが不要になるため高速な検索が可能です。ただし、インデックスデータのみで高速に処理させるためには、該当のレコードが存在するページが、すべてのトランザクションから取り出し可能な状態になっている必要があり、その情報は可視性マップ(注1)から取得されます。そのケースに該当する例としては、部署データなどの基本的に変更の殆どないマスターデータのテーブルを検索する場合が挙げられます。以下に、その動作概要を示します。

注1:可視性マップ(ビジビリティマップ)の説明は、「PostgreSQLのアーキテクチャー概要」を参照してください。

Index Only Scanによるインデックス活用例
図7 Index Only Scanによるインデックス活用例

(1)Index Only Scanによりインデックスを検索する。
(2)SELECT文の条件に指定されたレコードの存在するページの可視性マップをチェックする。
(3)可視性マップをチェックした結果、ページすべてがトランザクションとして取り出し可能であるかどうか判断する。
可能である場合は、ページにアクセスせずインデックスのデータを取得する。
可能でない場合は、実際にページをアクセスし、取り出しが可能かどうかを判断した上でデータを取得する。

そのため、(3)において、ページすべてがトランザクションとして取り出し可能である率が高い程、効果が見込めます。
なお、可視性マップは、1ページ当たり2ビットのデータでありファイルサイズとしては小さいため、可視性マップへのアクセスによるI/O増加に比べて、テーブルデータへのアクセスによるI/O減少の効果が高くなります。

2.1.2 複合インデックス作成時のポイント

インデックス定義はより絞り込める条件のカラムから順番に記述する、ただし例外あり

複数カラムを組み合わせて1つのインデックスが作成できる「複合インデックス」を利用する場合、基本的に、データ量をより少なく絞り込める条件をもつカラムから順にインデックスカラムを記述することで高速に絞り込むことができます。例えば、カラムc1よりも、カラムc2の方がより少なく絞り込める場合、以下のようにインデックスを定義します。

ソースコード5

しかし、範囲の条件を記述する場合は、より絞り込める順番に書くよりも、範囲の条件を後に書いた方が良い場合もあるため、注意が必要です。その例を挙げて、実際の動作を確認してみます。準備として、以下のようなテーブルを作成し、テストデータも作成します。

ソースコード6

まずは、以下のSQLのように、カラムnumが範囲の条件になっているケースを見てみます。

ソースコード7

この場合、typeは300,000分の100,000(3分の1)に絞り込め、numは300,000分の3,000(100分の1)に絞り込めます。そのため、より絞り込めるカラムnumから順番にインデックスを定義し、実行計画を確認してみます。なお、共有バッファーからの読み取りページ数や、ファイルからの読み取りブロック数が確認できるよう、EXPLAINコマンドにBUFFERSオプションも追加します。

ソースコード8

比較のために、CREATE INDEXで指定するカラムの順を変更し、再度、実行計画を確認してみます。

ソースコード9

利用されたバッファー数(Buffers:)を見ると、前者の18に対して、後者の方が13と少なくなっており、範囲の条件を後にした方が利用するバッファー数が少なく、結果的に処理時間も速くなっています。このように、範囲の条件を利用する際には、定義を後にした方がパフォーマンスが良くなる場合があるため、実際に確認してみることをお勧めします。

2.1.3 SQL文記述時におけるインデックスの有効な利用方法

SQLのOR条件式を工夫することで、インデックスの絞り込みを有効にする

SQL文にOR条件が記述されているとき、プランナーは、その条件を使ってインデックスを利用しようとすると、インデックス検索2回とマージ処理1回を行うよう実行計画を立てます。これは、処理コストが高く、処理自体が複雑なため処理に時間を費やします。プランナーのコスト計算によっては、シーケンシャルスキャンによる検索の方が処理コストが低いと見積もられる場合もあり、いずれにしても、処理に時間がかかる結果になります。
この対策としては、OR条件のものをまとめて1つの条件にして、OR条件のない条件を新たに追加できないか考えます。1つにまとめた新たな条件と今までの条件を並列に記述しておくことで検索結果を変えずにインデックスによる絞り込みを有効にすることができます。

例を挙げて説明します。日付(date)と時間(time)が別々のカラムで構成されるテーブルにおいて、2019年4月1日 12時以降のデータが欲しい場合は、以下のような条件式となります。

ソースコード10

まず、上記のカラムdate、timeのインデックスを利用して検索しようとすると、プランナーは date > '2019/4/1' の条件で検索し、その後、date = '2019/4/1' AND time >= '12:00:00' の条件でも検索します。次にこれらの結果をマージするよう実行計画を立てます。この処理はコストが高いため、パフォーマンスが出ないことが考えられます。

SQLにOR条件がある場合の処理の流れ
図8 SQLにOR条件がある場合の処理の流れ

次に、実際の動作を確認してみます。準備として、以下のようなテーブルを作成し、テストデータも作成します。

ソースコード11

カラムdateとtimeのインデックスを定義し、SELECT文の実行計画を確認してみると、インデックス検索2回とマージ処理1回の動作が行われている事が確認できます。

ソースコード12

そこで、ORの両辺にあるdateの条件が両方とも date >= ‘2019/4/1’ を満たすので、この条件をANDで追加します。

ソースコード13
追加するAND条件
図9 追加するAND条件

その実行計画を確認してみると、インデックス検索において追加した条件で絞り込み【1】、インデックス検索で利用しなかった条件でフィルタリング【2】することでデータを取り出せていることが分かります。その結果、1回のインデックス検索で範囲を絞って検索を実施することができるため、処理時間の短縮につながります。

ソースコード14

関数や演算を利用した条件なら「式インデックス」を利用する

SQLの条件文において、カラムに対して関数や演算を利用している場合、カラム名のみでインデックスを作成しても、そのインデックスは利用されません。このような場合には、関数や演算の結果をインデックス化する「式インデックス」を利用してください。「式インデックス」を利用すると、関数や演算結果をインデックス化できるため、インデックスによる絞り込みが利用でき、高速な検索が可能になります。
例えば、大文字小文字を区別せずに文字列を比較するために、以下のようなlower関数を使用した条件文を記述します。

ソースコード15

この場合にインデックスを利用するためには、以下のようにlower関数の結果をインデックスに定義します。

ソースコード16

参考

WHERE句の条件文で異なるデータ型による比較を行った場合の影響について

WHERE句の条件文において、列定義と比較対象のデータ型が異なると、パーサは実行計画を生成する際に、列定義のデータ型を型変換してしまう場合があります。すると、インデックスを作成したときのデータ型が変わることで、インデックスが使われなくなることがあるため、注意が必要です。以下にその例を示します。

【準備】

ソースコード17

条件文のデータ型を等しく指定した場合(比較対象がinteger型)には、インデックスが利用されます。

ソースコード18

次に、条件文のデータ型が異なる場合(比較対象がnumeric型)は、列定義idがnumericに型変換されることで、インデックスは使われず、シーケンシャルスキャン(Seq Scan)が選択されます。なお、PL/pgSQLなどで比較対象の「1::numeric」のところに、numeric型の変数を利用したときも同様です。

ソースコード19

2.2 実行計画を評価し制御する

PostgreSQLは、autovacuumによって定期的に最新化される統計情報を基に最適な実行計画を作成しますが、テーブルの更新頻度が高くて常にデータの状況が変化している場合など、統計情報と実際のデータとのかい離が発生し、非効率で時間のかかる実行計画が作成されることで、パフォーマンスが不安定になる場合があります。
この場合には、まず、実行計画を確認して時間を費やしている箇所を特定し、インデックス利用やSQL文の見直しによるパフォーマンスチューニングが正しく行われているかを確認します。その上で、パフォーマンスを安定させるために、pg_hint_planを用いて実行計画の結果を制御したり、pg_dbms_statsを用いて統計情報を固定化したりすることを検討します。

実行計画から時間を費やしている箇所を特定する

実際の実行計画を参考に、SQLが時間を費やしている箇所を特定し、妥当性を確認します。
準備として、以下のようなテーブルを作成し、テストデータも作成します。

ソースコード20

以下のSELECT文について、実行計画を出力します。

ソースコード21

各処理に費やした時間については、以下の結果になります。
【上位ノード】131.686 - Seq Scanの時間(131.519) - Index Scanの時間(0.132) = 0.035 ms
【下位ノード1】131.519 × 実行回数1回 = 131.519 ms
【下位ノード2】0.012 × 実行回数11回 = 0.132 ms

これらの情報を基に、実行計画の妥当性を確認します。例えば、Seq Scanで時間を費やしている場合はインデックスを追加することを検討します。しかし、loopsの回数が多く時間を費やしている場合は、結合方法を変更するなど、ノードの要素を強制的に変更することも検討してください。結合方法の変更については次の項目で説明しますが、コマンド「SET enable_nestloop = off」により一時的にNested Loopを抑止することで行うことも可能です。
なお、【上位ノード】と【下位ノード1】において、推定時の行数(rows)が1であるのに対し、実行時の行数(rows)は11になっています。これは、統計情報が最新化されていない可能性が考えられます。この場合は、autovacuumの実行頻度の設定を見直すか、あるいは、手動でANALYZEコマンドを実行することで解決できます。

参考

カーソル利用時の実行計画について

カーソルを利用してデータを取得する場合は、設定ファイルpostgresql.confのcursor_tuple_fractionパラメーターの値に従い、起動を高速にする実行計画を作成します。これは、1つ目の最初のレコード(タプル)を取り出すためのコストが小さくなるようにしているためです。そのため、カーソルを利用する場合とそうでない場合とで、実行計画が変わることがあることに注意してください。

pg_hint_planを用いて、実行計画を制御する

実行計画を見て利用して欲しいインデックスや結合方法が使われていなかった場合、ヒント句を指定し、希望する方法でアクセスするように制御することで、パフォーマンス改善を実施します。詳細は「pg_hint_planで実行計画を制御する」を参照してください。

pg_dbms_statsを用いて、統計情報を固定化する

テーブルの更新頻度が高く、統計情報の最新化が間に合わない場合など、実行計画作成時に正しい統計情報が参照できないような場合に、統計情報を固定し、常に一定の実行計画が作成されるようにして、パフォーマンス劣化を防ぎます。詳細は「pg_dbms_statsで統計情報を固定化して、実行計画を制御する」を参照してください。

2.3 クライアント側で無駄を削減する

PostgreSQLのクライアント側でSQLを記述する際の工夫や、パフォーマンス改善につながる手法について紹介します。ここでは以下の内容で説明します。

何度も実行するSQLは、プリペアド文を定義し再利用する

パラメーターだけ異なるSQL文を何度も実行する場合、プリペアド文(PREPARE)を定義し、実行計画を再利用させることで、実行計画の作成が繰り返されることを防止し、パフォーマンスが改善できます。プリペアド文は、汎用的な実行計画を作成し、その実行計画を利用するかどうかをPostgreSQL内部で自動的に判断しています。具体的には以下のように動作します。

1)プリペアド文で準備したSQLを繰り返し実行する時に、最初の5回目までは、毎回、パラメーターに合わせた実行計画(実行計画A1からA5とします)を作成します。
2)6回目以降に実行する時は、パラメーターの値が未設定である汎用的な実行計画(実行計画Bとします)を作成し、今まで作成した実行計画A1からA5までの平均コストと、実行計画Bのコストを比較して、今後、汎用的な実行計画を利用するか否かを判定します。
3)実行計画Bのコストが実行計画Aの平均コストよりもそれほど大きくない場合、それ以降のSQL実行で実行計画を毎回作成せず、汎用的な実行計画(実行計画B)を利用します。
あるいは、実行計画Bのコストが実行計画A1からA5までの平均コストよりもかなり大きい場合は、パラメーターに合わせた実行計画を毎回作成して利用します。

なお、プリペアド文の中で使用されているデータベースオブジェクトが定義(DDL)に変更があった場合、もしくは、search_pathの値が変わった場合に、上記の解析処理と計画作成が再度行われます。

PostgreSQL 12からは、設定ファイルpostgresql.confにplan_cache_modeパラメーターが追加され、より柔軟な設定が可能になりました。以下の3パターンから選択することができます。

  • 自動判定(上記の方法、デフォルト値)
  • 必ず汎用的な実行計画を利用する(理想的なプランについて、パラメーター値への依存度が低い場合に有効)
  • 必ずその都度実行計画を作成する(理想的なプランについて、パラメーター値への依存度が高い場合に有効)

コネクションプーリングを使い、接続処理を省略する

頻繁にPostgreSQLへの接続と切断を繰返すシステムのような場合、このコネクション処理がオーバーヘッドになります。その場合は、コネクションプーリングを用いることで、すでに接続されているコネクションを再利用でき、パフォーマンス改善につなげることができます。コネクションプーリングは、Pgpool-IIを利用したり、JDBCやNpgsql(.NET Data Provider)などのインターフェイスに組み込まれているものを利用したり、クライアント側でコネクションプーリング機能を作り込んだりすることで実現できます。

ユーザー定義関数を用いて処理を関数化し、ネットワーク通信を省略する

クライアント側で行っていた定型のSQL処理を、ユーザー定義関数としてPostgreSQLサーバー側に配置することで、サーバー側で処理を完結させ、SQLを発行するたびに発生していたネットワーク通信を省略することでパフォーマンスが改善できます。ただし、ユーザー定義関数のPL/pgSQLなどは、内部での初期化処理や記述方法によっては、処理を関数化する前よりも遅くなることもあるため、試行しながら進める必要があります。

フェッチサイズを調整する

PostgreSQLからデータを取得するプロセスは「フェッチ」と呼ばれます。このフェッチ処理では、大きなデータ量を扱う場合、一度に取得するデータ量を増やし、通信の実行回数を減少させることで、データの受け渡しが効率化され、パフォーマンスの改善につながることがあります。JDBCおよびODBCではパラメータで調整できますが、組込みSQLではアプリの改修が必要になります。具体的な手段としては、以下の方法があります。

  • JDBC

    接続文字列に設定できるdefaultRowfetchSizeパラメーターで調整することができます。

  • ODBC

    Cache Sizeオプションで調整することができます。

  • 組込みSQL

    PostgreSQLの埋込みSQLには、JDBCやODBCと同様の機能を持つパラメータがないため、データ取得時に複数の行をまとめて配列に格納し、後続のデータ取得処理は配列から行うようにします。
    具体的には、「FETCH count :配列」のようにします。そのため取得できる行数を変更する場合、アプリケーションの改修が必要です。

PostgreSQLのパフォーマンスチューニングの重要なポイントである「探し」についての考え方と手法について解説しました。次回は、「基盤」をテーマに解説します。

2025年10月14日更新

こちらもおすすめ

富士通のソフトウェア公式チャンネル(YouTube)

富士通のミドルウェア製品のご紹介や各種イベント・セミナーの講演内容、デモンストレーションなどの動画をご覧いただけます。

PostgreSQLについてより深く知る

PostgreSQLに興味をお持ちのお客様はこちらのコンテンツもお勧めです。ぜひご覧ください。

Enterprise Postgres

Enterprise Postgres(エンタープライズ ポストグレス)は富士通の技術でPostgreSQLのセキュリティ・性能・信頼性を強化したデータベースソフトウェアです。ビジネスユースで安心してご利用いただけるPostgreSQLを実現します。
オフィスで、女性が男性にラップトップを見せながら会話しています。

PostgreSQL インサイド ~ PostgreSQLに関する富士通の情報がここに ~

PostgreSQLに関する富士通の情報がここに。OSSデータベースの企業利用をお考えのお客様必見です。
広々としたモダンなオフィスで働く多様なチーム。