13.2. プランナで使用される統計情報

前節で説明した通り、問い合わせプランナは、より良い問い合わせ計画を選択するために問い合わせによって取り出される行数の推定値を必要としています。 本節では、システムがこの推定に使用する統計情報について簡単に説明します。

統計情報の1つの構成要素は、各テーブルとインデックスの項目の総数と、各テーブルとインデックスが占めるディスクブロック数です。 この情報はpg_classreltuplesrelpages列に保持されます。 以下のような問い合わせによりこれを参照することができます。

SELECT relname, relkind, reltuples, relpages FROM pg_class WHERE relname LIKE 'tenk1%';

    relname    | relkind | reltuples | relpages
---------------+---------+-----------+----------
 tenk1         | r       |     10000 |      233
 tenk1_hundred | i       |     10000 |       30
 tenk1_unique1 | i       |     10000 |       30
 tenk1_unique2 | i       |     10000 |       30
(4 rows)

ここで、tenk1とそのインデックスには10000行が存在し、そして、(驚くには値しませんが)インデックスはテーブルよりもかなり小さなものであることが判ります。

効率をあげるため、reltuplesrelpagesは処理の度に更新されず、したがって通常は(プランナの目的には十分な)概算値のみ所有しています。 テーブルが作成された時これらはダミー値(現在それぞれ1000と10)で初期化されます。 今の所、これらは特定のコマンド、VACUUMANALYZECREATE INDEXによって更新されます。 スタンドアローンのANALYZE、つまり、VACUUMの一部ではないコマンドはテーブルの全ての行を読みませんので、reltuplesの概算値を生成します。

ほとんどの問い合わせは、検証される行を制限するWHERE句があることによって、テーブル内の行の一部のみを取り出します。 従って、プランナはWHERE句の選択性、つまり、WHERE句の各条件にどれだけの行が一致するか、を推定する必要があります。 この処理に使用される情報はpg_statisticシステムカタログ内に格納されます。 pg_statistic内のエントリは、ANALYZEVACUUM ANALYZEコマンドによって更新され、また一から更新がかかったとしても常に概算値になります。

統計情報を手作業で確認する場合、pg_statisticを直接参照するのではなく、pg_statsビューを参照する方が良いでしょう。 pg_statsはより読み易くなるように設計されています。 さらに、pg_statsは誰でも読みとることができますが、pg_statisticはスーパーユーザのみ読みとることができます。 (これは、非特権ユーザが統計情報から他人のテーブルの内容に関わる事項を読みとることを防止します。pg_statsビューは現在のユーザが読みとることができるテーブルに関する行のみを表示するよう制限されています。) 例えば、以下を行うことができます。

SELECT attname, n_distinct, most_common_vals FROM pg_stats WHERE tablename = 'road';

 attname | n_distinct |                                                                                                                                                                                  most_common_vals                                                                                                                                                                                   
---------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 name    |  -0.467008 | {"I- 580                        Ramp","I- 880                        Ramp","Sp Railroad                       ","I- 580                            ","I- 680                        Ramp","I- 80                         Ramp","14th                          St  ","5th                           St  ","Mission                       Blvd","I- 880                            "}
 thepath |         20 | {"[(-122.089,37.71),(-122.0886,37.711)]"}
(2 rows)

項43.35pg_stats の詳細を説明します。

pg_statisticに格納される情報量、特に、それぞれの列に対するmost_common_vals内とhistogram_bounds配列のエントリの最大数は、ALTER TABLE SET STATISTICSコマンドによって列毎に、default_statistics_target実行時パラメータを設定することによってグローバルに設定することができます。 現在のデフォルトの上限は10エントリです。 この上限を上げることで、特に、非正規分布のデータを持つ列でより正確なプランナの推定が行われますが、pg_statisticにより多くの容量が必要になり、多少推定計算にかかる時間が多くなります。 反対に上限を下げることは、単純なデータ分布の列に対して順当です。