11.5. 複数のインデックスの組み合わせ

単一のインデックススキャンは、インデックスの列をその演算子クラスの演算子で使用する問い合わせ句と、それをAND結合したものでのみ使用されます。 例えば、(a, b)というインデックスとWHERE a = 5 AND b = 6という問い合わせでは、インデックスが使用されます。 しかし、WHERE a = 5 OR b = 6のような問い合わせではインデックスは直接使用されません。

幸いにも、PostgreSQLは、単一のインデックススキャンでは実装できない場合を扱うために、複数のインデックス(同じインデックスの複数回使用を含む)を組み合わせる機能を持ちます。 システムは複数のインデックススキャンを跨がる、条件のANDまたはORを形成します。 例えば、 WHERE x = 42 OR x = 47 OR x = 53 OR x = 99という問い合わせは、問い合わせ句の1つを使用してx上のインデックスをスキャンする4つのスキャンに分割することができます。 その後、これらのスキャンの結果はOR演算でまとめられ、結果を生成します。 他の例としてxyに別個のインデックスがある場合を考えます。 WHERE x = 5 AND y = 6のような問い合わせに対して取り得る実装は、適切な問い合わせ句で各インデックスを使用し、インデックスの結果をANDでまとめ、結果行を識別することです。

複数のインデックスを組み合わせるために、システムは必要なインデックスそれぞれをスキャンし、インデックス条件に一致するものと報告されたテーブル行の位置を与えるためにメモリ上にビットマップを準備します。 その後、このビットマップは問い合わせで必要とされたように、ANDまたはOR演算されます。 最後に、実際のテーブル行がアクセスされ、返されます。 テーブル行は物理的な順番でアクセスされます。 ビットマップにこの順番で格納されているからです。 これは、元のインデックスの順序が失われていることを意味します。 そのため、もし問い合わせがORDER BY句を持つ場合、この他のソート手続きが必要となります。 この理由、および、追加のインデックススキャンそれぞれのために余計な時間が加わることから、プランナは追加のインデックスが同様に使用できる場合であっても、単純なインデックススキャンを選択することがあります。

もっとも単純なアプリケーション以外のほとんどすべてのアプリケーションでは、インデックスの組み合わせが変動することが有用となる場合があります。 そして、データベース開発者はどのようなインデックスを提供するかを決定するためにトレードオフを行わなければなりません。 複数列インデックスが最善な場合がありますし、別々のインデックスを作成し、インデックスの組み合わせ機能に依存する方が優れている場合もあります。 例えば、作業にx列のみを含む場合とy列のみを含む場合、両方の列を含む場合が混在する問い合わせが含まれる場合、xyに対し、別個に2つのインデックスを作成し、両方の列を使用する問い合わせを処理する時にインデックスの組み合わせに依存することを選ぶことができます。 また、(x, y)に対する複数列インデックスを作成することもできます。 両方の列を含む問い合わせでは、通常このインデックスの方がインデックスの組み合わせよりも効率的です。 しかし、項11.3で説明した通り、yのみを含む問い合わせではほとんど意味がありません。 従って、このインデックスのみとすることはできません。 複数列インデックスの組み合わせやyに対する別のインデックスが合理的に提供します。 xのみを含む問い合わせでは、複数列インデックスを使用することができます。 しかし、これはより大きくなりますので、x のみインデックスよりも低速になります。 最後の別方法は、3つのインデックスすべてを作成することです。 しかしこれはおそらく、テーブルの検索頻度が更新頻度よりもかなり高く、3種類の問い合わせすべてが良く使用される場合のみ合理的です。 問い合わせの中の1つの頻度が他よりも少なければ、おそらく良く使用される種類にもっとも合うように2つだけインデックスを作成した方がよいでしょう。