説明した通り、問い合わせプランナは、より良い問い合わせ計画を選択するために問い合わせによって取り出される行数の推定値を必要としています。本節では、システムがこの推定に使用する統計情報について簡単に説明します。統計情報の1つの構成要素は、各テーブルとインデックスの項目の総数と、各テーブルとインデックスが占めるディスクブロック数です。この情報はpg_classのreltuplesとrelpages列に保持されます。以下のような問い合わせによりこれを参照することができます。rows)ここで、tenk1とそのインデックスには10000行が存在し、そして、(驚くには値しませんが)インデックスはテーブルよりもかなり小さなものであることがわかります。効率を上げるため、reltuplesとrelpagesは処理の度には更新されず、したがって通常は多少古い値のみ所有しています。INDEXなどの一部のDDLコマンドによって更新されます。テーブル全体をスキャンしないVACUUM、ANALYZE操作(一般的な状況です)は、スキャンされたテーブルの部分に基づいてreltuples値を漸次更新し、概算値を生成します。いずれの場合でもプランナは、現在の物理的なテーブルサイズに合わせるためにpg_classから検索した値を調整して、より高精度な近似値を得ます。ほとんどの問い合わせは、検証される行を制限するWHERE句によって、テーブル内の行の一部のみを取り出します。したがって、プランナはWHERE句の選択性、つまりWHERE句の各条件にどれだけの行が一致するかを推定する必要があります。この処理に使用される情報はpg_statisticシステムカタログ内に格納されます。ANALYZEコマンドによって更新され、また1から更新がかかったとしても常に概算値になります。統計情報を手作業で確認する場合、pg_statisticを直接参照するのではなく、pg_statsビューを参照する方が良いでしょう。pg_statsはより読みやすくなるように設計されています。pg_statsは誰でも読み取ることができますが、pg_statisticはスーパーユーザのみ読み取ることができます。(これは、非特権ユーザが統計情報から他人のテーブルの内容に関わる事項を読み取ることを防止します。pg_statsビューは現在のユーザが読み取ることができるテーブルに関する行のみを表示するよう制限されています。以下を行うことができます。rows)同じ列に対して2行が表示されていることに注意してください。1つはroadテーブルが始まる継承階層(inherited=t)全体に相当し、もう1つはroadテーブル自身(inherited=f)のみを含むものです。STATISTICSコマンドによって列ごとに、default_statistics_target設定パラメータを設定することによってグローバルに設定することができます。現在のデフォルトの上限は100エントリです。この上限を上げることで、特に、少し変わったデータ分布を持つ列でより正確なプランナの推定が行われますが、pg_statisticにより多くの容量が必要になり、多少推定計算にかかる時間が多くなります。反対に上限を下げることは、単純なデータ分布の列に対して順当です。プランナによる統計情報の使用に関する詳細については第70章を参照してください。問い合わせ句で使われている複数列に相関性があることにより、悪い実行計画を実行する遅いクエリがしばしば観察されます。プランナは通常複数の条件がお互いに独立あるとみなしますが、列の値に相関性がある場合はそれは成り立ちません。通常の列ごとの統計情報は、それが個々の列ごとであるという性質上、列をまたがる相関性に関する知識を把握することはできません。PostgreSQLは、多変量統計情報を計算することができ、それによってそうした情報を把握することができます。列の組み合わせの数は非常に大きいため、自動的に多変量統計情報を計算するのは現実的ではありません。代わりに、サーバが興味のある列の集合にまたがる統計情報を得るように指示する目的で、拡張統計情報オブジェクト(しばしば単に統計情報オブジェクトと呼ばれます)を作成することができます。STATISTICSで作成します。したオブジェクトを作っても、単に統計情報として興味があることを示すカタログエントリが作られるだけです。(手動のコマンドを起動あるいはバックグラウンドでの自動ANALYZE)が行います。収集したデータは、pg_statistic_extカタログで参照することができます。通常の単一列統計情報の計算に使うのと同じテーブル行のサンプルに基づき、ANALYZEは、拡張統計情報を計算します。(前節で述べたように)テーブルあるいはそのテーブルの対象となる列統計情報の増やすと、サンプルのサイズも増えるので、より大きな統計情報の対象を使うと、通常、より精度の高い拡張統計情報を得られますが、計算に費やす時間も増えます。次の節では、現在サポートしている拡張統計情報の種類を説明します。関数従属性もっとも単純な拡張統計情報は、データベースの正規形の定義で使われる考え方である、関数従属性を追跡します。aの値に関する知識がbの値を決定するのに十分であるとき、列bは列aに関数的に従属していると言います。これはすなわち、同じaの値を持ちながら、異なるbの値を持つ二つの行は存在しないということです。完全に正規化されたデータベースでは、関数従属性は主キーと超キーにのみ存在します。実際には様々な理由でデータの集合は完全には正規化されません。性能上の理由により非正規化するというのが典型的な例です。完全に正規化されたデータベースにおいても、ある列の間に部分的な相関関係が存在することがあり、これは部分的関数従属性として表現されます。ある問い合わせでは、関数従属性が存在することが見積もりの精度に直接影響を与えます。問い合わせに独立した列と依存する列の両方に関する条件が含まれていると、依存する列に関する条件はそれ以上結果サイズを小さくしません。関数従属性に関する知識がなければ、クエリプランナはそれらの条件が独立であると見なし、結果サイズの過少見積もりすることになります。プランナに関数従属性について知らせるために、ANALYZEは列をまたがる依存性の強さを収集することができます。すべての列の集合間の依存性度合いを調査するのは、受け入れられないほど高価になります。そこでデータ収集は、dependenciesオプションで定義された統計情報オブジェクトの中に一緒に現れた列のグループに制限されます。code)が完全に列5(city)を決定しているので、係数は1.0です。codeで表現されている多くのcity(58%)が存在するということになります。関数従属する列を伴うクエリの選択率を計算する際、過小評価を行わないように、プランナは依存性係数を使って条件ごとの選択率を調整します。今のところ、列と定数を比較する単純な等価条件を考慮する際にしか関数従属性は適用されません。LIKEその他の条件の見積もりを改善するのには使われません。関数従属性による見積もりでは、プランナは関係する列は両立で、冗長であると見なします。それらが両立でなければ、正しい見積もりは0行となりますが、その可能性は考慮されません。次のクエリを見てください。'94105';プランナは、選択率が変わらないという正しい推定に基づきcity句を無視します。これを満たす行が0行であるにもかかわらず、次の問い合わせでも同じ推測をします。これを結論付けるだけの十分な情報を提供しません。多くの実用的な場合には、この前提は通常満たされます。codeだけを許すGUIが備わっているかもしれません。なければ、関数従属性は実行可能なオプションではないかもしれません。それぞれの列で異なる値の数を保持します。bのように、一つ以上の列を組み合わせての異なる値の数の見積もりは、プランナに単一列の統計情報だけしか与えられない場合は、しばしば間違ったものになり、プランナは悪いプランの選択をしてしまいます。見積もり改善のために、列のグループに対してANALYZEはN個別統計情報を収集することができます。以前述べたのと同様に、可能なすべての列のグループに対してこれを行なうのは現実的ではありません。列リストの中から、可能な二つ以上の列の組み合わせそれぞれに対してデータが収集されます。codeのテーブルのN個別値計数は次のようになります。row)この例では、33178の異なる値を持つ列の組み合わせが三つあることを示しています。codeとcity、cityとstateです。codeだけがテーブル中でユニークであることから期待されます。cityとstateの組み合わせには、27435だけの異なる値があります。グループ化で実際に使用する列の組み合わせで、かつグループ数の見積もり間違いによって悪いプランをもたらすものに対してだけ、ndistinct統計情報オブジェクトを作ることをお勧めします。ないと、ANALYZEサイクルは単に無駄になります。明示的なJOIN句でプランナを制御する。