前節で説明した通り、問い合わせプランナは、より良い問い合わせ計画を選択するために問い合わせによって取り出される行数の推定値を必要としています。 本節では、システムがこの推定に使用する統計情報について簡単に説明します。
統計情報の1つの構成要素は、各テーブルとインデックスの項目の総数と、各テーブルとインデックスが占めるディスクブロック数です。
この情報はpg_classのreltuplesとrelpages列に保持されます。
以下のような問い合わせによりこれを参照することができます。
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行が存在し、そして、(驚くには値しませんが)インデックスはテーブルよりもかなり小さなものであることがわかります。
効率を上げるため、reltuplesとrelpagesは処理の度には更新されず、したがって通常は多少古い値のみ所有しています。
これらはVACUUM、ANALYZE、CREATE INDEXなどの一部のDDLコマンドによって更新されます。
テーブル全体をスキャンしないVACUUM、ANALYZE操作(一般的な状況です)は、スキャンされたテーブルの部分に基づいてreltuples値を漸次更新し、概算値を生成します。
いずれの場合でもプランナは、現在の物理的なテーブルサイズに合わせるためにpg_classから検索した値を調整して、より高精度な近似値を得ます。
ほとんどの問い合わせは、検証される行を制限するWHERE句によって、テーブル内の行の一部のみを取り出します。
したがって、プランナはWHERE句の選択性、つまりWHERE句の各条件にどれだけの行が一致するかを推定する必要があります。
この処理に使用される情報はpg_statisticシステムカタログ内に格納されます。
pg_statistic内の項目は、ANALYZEとVACUUM ANALYZEコマンドによって更新され、また1から更新がかかったとしても常に概算値になります。
統計情報を手作業で確認する場合、pg_statisticを直接参照するのではなく、pg_statsビューを参照する方が良いでしょう。
pg_statsはより読みやすくなるように設計されています。
さらに、pg_statsは誰でも読み取ることができますが、pg_statisticはスーパーユーザのみ読み取ることができます。
(これは、非特権ユーザが統計情報から他人のテーブルの内容に関わる事項を読み取ることを防止します。
pg_statsビューは現在のユーザが読み取ることができるテーブルに関する行のみを表示するよう制限されています。)
例えば、以下を行うことができます。
SELECT attname, inherited, n_distinct,
array_to_string(most_common_vals, E'\n') as most_common_vals
FROM pg_stats
WHERE tablename = 'road';
attname | inherited | n_distinct | most_common_vals
---------+-----------+------------+------------------------------------
name | f | -0.363388 | I- 580 Ramp+
| | | I- 880 Ramp+
| | | Sp Railroad +
| | | I- 580 +
| | | I- 680 Ramp
name | t | -0.284859 | I- 880 Ramp+
| | | I- 580 Ramp+
| | | I- 680 Ramp+
| | | I- 580 +
| | | State Hwy 13 Ramp
(2 rows)
同じ列に対して2行が表示されていることに注意してください。
1つはroadテーブルが始まる継承階層(inherited=t)全体に相当し、もう1つはroadテーブル自身(inherited=f)のみを含むものです。
ANALYZEによりpg_statisticに格納される情報量、具体的には、それぞれの列に対するmost_common_vals内とhistogram_bounds配列のエントリの最大数は、ALTER TABLE SET STATISTICSコマンドによって列ごとに、default_statistics_target設定パラメータを設定することによってグローバルに設定することができます。
現在のデフォルトの上限は100エントリです。
この上限を上げることで、特に、少し変わったデータ分布を持つ列でより正確なプランナの推定が行われますが、pg_statisticにより多くの容量が必要になり、多少推定計算にかかる時間が多くなります。
反対に上限を下げることは、単純なデータ分布の列に対して順当です。
プランナによる統計情報の使用に関する詳細については65章プランナは統計情報をどのように使用するかを参照してください。