PostgreSQLでは、インデックスのメンテナンスまたはチューニングは必要ありませんが、どのインデックスが実際の問い合わせで使われているかを確認することは、やはり重要です。
個々のコマンドでのインデックスの使用状況は、EXPLAINコマンドで検証できます。
この目的のための用例を14.1. EXPLAIN
の利用に示します。
また、27.2. 統計情報コレクタに示す通り、稼働中のサーバにおけるインデックス使用状況の全体的な統計情報を取り出すこともできます。
どのインデックスを作成すべきかを判断するための一般的な手順を定めることは困難です。 これまでの節では、例として典型的なケースをいくつか記述してきました。 十分な検証がしばしば必要です。 本節の残りで、検証のためのヒントをいくつか説明しておきます。
まず、必ずANALYZEコマンドを実行してください。
このコマンドにより、テーブル内の値の分布に関する統計情報を収集します。
この情報は、問い合わせにより返される行数を推測する際に必要となります。
推測された行数は、利用できる各問い合わせ計画に実際のコストを割り当てるために、プランナで必要となります。
実際の統計情報が少しでも欠如している場合、何らかのデフォルト値が仮定されます。
このデフォルト値は、ほぼ間違いなく不正確です。
したがって、ANALYZE
コマンドを実行せずに、アプリケーションのインデックス使用状況を検証しても、あまり意味がありません。
より詳細な情報は23.1.3. プランナ用の統計情報の更新と23.1.6. 自動バキュームデーモンを参照してください。
検証には、実際に使用するデータを使ってください。 テストデータを使ってインデックスを作成した場合、テストデータに必要なインデックスはわかりますが、それ以上はわかりません。
非常に小さなテストデータを使用することも、結果に特に致命的な影響を与えます。 100,000行から1,000行を選択する場合は、インデックスが使用される可能性がありますが、100行から1行を選択する場合はインデックスはまず使用されません。 なぜなら、100行はおそらく1つのディスクページに収まるため、1ページを逐次読み取るよりも高速な計画は存在しないからです。
また、アプリケーションがまだ実動していない場合、テストデータを作成しなければならないことがよくありますが、その際にも注意が必要です。 非常に類似した値や、完全にランダムな値、またはソートされた順序で値が挿入されている場合は、その統計情報は、実際のデータの分布とかけ離れたものになってしまいます。
インデックスが使用されていない場合、テストのためにインデックスを強制的に使用するようにすると便利です。
各種の計画型を無効にするかを設定できる実行時パラメータがあります
(18.7.1. プランナメソッド設定を参照してください)。
例えば、最も基本的な計画であるシーケンシャルスキャン(enable_seqscan
)および入れ子状ループ結合(enable_nestloop
)を無効に設定すると、システムは別の計画を使用するように強制されます。
そのような設定を行っても、システムがシーケンシャルスキャンや入れ子状ループ結合を選択する場合は、インデックスを使用しない理由としておそらくもっと根本的な理由があるということになります。
例えば、問い合わせの条件がインデックスに一致しない、などが考えられます。
(どのような問い合わせで、どのようなインデックスを使用できるかは、前節で説明済みです。)
強制的にインデックスを使うように設定し、インデックスを使用している場合は、次の2つの状況が考えられます。
システムの判断が正しく、インデックスの使用が実際には適切ではないという状況と、問い合わせ計画のコスト推定が実情を反映していない状況です。
したがって、インデックスを使った問い合わせの実行時間と、使わない場合の実行時間を計測する必要があります。
この場合、EXPLAIN ANALYZE
コマンドが便利です。
コスト推定が間違っていると判明した場合、やはり2つの状況が考えられます。 総コストは、各計画ノードの行単位のコストに、計画ノードの推定選択度を掛けることで算出されます。 計画ノードのコスト推定は、実行時パラメータによって設定することができます (18.7.2. プランナコスト定数を参照してください)。 推定選択度が不正確であるのは、統計情報が不十分であるのが原因です。 統計情報収集用のパラメータを調節することによって、この状況を改善することができます (ALTER TABLEを参照してください)。
コストを適切に調節できない場合は、明示的にインデックスを使用する必要が考えられます。 あるいは、PostgreSQL開発者に問題の調査を依頼することになるかもしれません。