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

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

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

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

       relname        | relkind | reltuples | relpages
----------------------+---------+-----------+----------
 tenk1                | r       |     10000 |      358
 tenk1_hundred        | i       |     10000 |       30
 tenk1_thous_tenthous | i       |     10000 |       30
 tenk1_unique1        | i       |     10000 |       30
 tenk1_unique2        | i       |     10000 |       30
(5 rows)

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

効率を上げるため、reltuplesrelpagesは処理の度には更新されず、したがって通常は多少古い値のみ所有しています。 これらはVACUUMANALYZECREATE INDEXなどの一部のDDLコマンドによって更新されます。 スタンドアロンのANALYZE、つまりVACUUMの一部ではないコマンドはテーブルの全ての行を読みませんので、reltuplesの概算値を生成します。 プランナは、現在の物理的なテーブルサイズに合わせるためにpg_classから検索した値を調整して、より高精度な近似値を持ちます。

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

統計情報を手作業で確認する場合、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.46pg_statsの詳細を説明します。

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