バージョンごとのドキュメント一覧

11.3. 複数列インデックス #

<title>Multicolumn Indexes</title>

An index can be defined on more than one column of a table. For example, if you have a table of this form: インデックスは、テーブルの2つ以上の列に定義することができます。 例えば、以下のようなテーブルがあるとします。

CREATE TABLE test2 (
  major int,
  minor int,
  name varchar
);

(say, you keep your <filename class="directory">/dev</filename> directory in a database...) and you frequently issue queries like: (例えば、/devディレクトリの内容をデータベースに保持していて)頻繁に下記のような問い合わせを発行するとします。

SELECT name FROM test2 WHERE major = constant AND minor = constant;

then it might be appropriate to define an index on the columns <structfield>major</structfield> and <structfield>minor</structfield> together, e.g.: このような場合、majorおよびminorという2つの列に1つのインデックスを定義する方が適切かもしれません。

CREATE INDEX test2_mm_idx ON test2 (major, minor);

Currently, only the B-tree, GiST, GIN, and BRIN index types support multiple-key-column indexes. Whether there can be multiple key columns is independent of whether <literal>INCLUDE</literal> columns can be added to the index. Indexes can have up to 32 columns, including <literal>INCLUDE</literal> columns. (This limit can be altered when building <productname>PostgreSQL</productname>; see the file <filename>pg_config_manual.h</filename>.) 現在、B-tree、GiST、GINおよびBRINインデックス型でのみ、複数キー列インデックスをサポートしています。 複数キー列を持つことができるかどうかは、INCLUDE列をインデックスに追加できるかどうかとは無関係です。 インデックスはINCLUDE列を含めて最大32列まで持つことができます。 (この上限は、PostgreSQLを構築する際に変更可能です。 pg_config_manual.hファイルを参照してください。)

A multicolumn B-tree index can be used with query conditions that involve any subset of the index's columns, but the index is most efficient when there are constraints on the leading (leftmost) columns. The exact rule is that equality constraints on leading columns, plus any inequality constraints on the first column that does not have an equality constraint, will always be used to limit the portion of the index that is scanned. Constraints on columns to the right of these columns are checked in the index, so they'll always save visits to the table proper, but they do not necessarily reduce the portion of the index that has to be scanned. If a B-tree index scan can apply the skip scan optimization effectively, it will apply every column constraint when navigating through the index via repeated index searches. This can reduce the portion of the index that has to be read, even though one or more columns (prior to the least significant index column from the query predicate) lacks a conventional equality constraint. Skip scan works by generating a dynamic equality constraint internally, that matches every possible value in an index column (though only given a column that lacks an equality constraint that comes from the query predicate, and only when the generated constraint can be used in conjunction with a later column constraint from the query predicate). 複数列に対するB-treeインデックスは、インデックス対象列の任意の部分集合を含む問い合わせ条件で使用できますが、もっともインデックスの効率が良いのは、先頭(左側)の列に制約がある場合です。 正確な規則は、先頭の列に対する等価制約、および等価制約を持たない先頭の列に対する不等式制約は、常にスキャン対象のインデックス範囲を制限するために使用されるということです。 これらの列の右側の列に対する制約はインデックスで検査されるため、常にテーブルへのアクセスを適切に抑えますが、必ずしもスキャンしなければならないインデックスの範囲を減らすわけではありません。 B-treeインデックススキャンでスキップスキャン最適化を効果的に適用できる場合は、インデックス検索を繰り返してインデックスを辿るときに、すべての列制約が適用されます。 これにより、(問い合わせの述語に含まれるもっとも重要度の低いインデックス列より前に位置する)1つまたは複数の列に従来の等価制約がない場合でも、読まなければならないインデックスの範囲を減らすことができます。 スキップスキャンは、インデックス列において取り得るすべての値と一致する動的な等価制約を内部的に生成することで機能しています(ただし、問い合わせの述語に含まれる等価制約のない列に対してのみ適用され、かつ生成された制約が問い合わせの述語に含まれる後続の列制約と組み合わせて使用できる場合に限ります)。

For example, given an index on <literal>(x, y)</literal>, and a query condition <literal>WHERE y = 7700</literal>, a B-tree index scan might be able to apply the skip scan optimization. This generally happens when the query planner expects that repeated <literal>WHERE x = N AND y = 7700</literal> searches for every possible value of <literal>N</literal> (or for every <literal>x</literal> value that is actually stored in the index) is the fastest possible approach, given the available indexes on the table. This approach is generally only taken when there are so few distinct <literal>x</literal> values that the planner expects the scan to skip over most of the index (because most of its leaf pages cannot possibly contain relevant tuples). If there are many distinct <literal>x</literal> values, then the entire index will have to be scanned, so in most cases the planner will prefer a sequential table scan over using the index. たとえば、(x, y)に対するインデックスと問い合わせ条件WHERE y = 7700では、B-treeインデックススキャンでスキップスキャン最適化を適用できる場合があります。 これは通常、問い合わせプランナがそのテーブルで使用可能なインデックスを考慮した時に、WHERE x = N AND y = 7700の検索を、Nで取り得るすべての値(または実際にインデックスに格納されているすべてのxの値)に対して繰り返す方法が最速であると想定している場合に発生します。 この方法は通常、xの個別値が非常に少なく、ほとんどのインデックスをスキップしてスキャンする(ほとんどのリーフページには関連するタプルが含まれないため)とプランナが期待する場合にのみ採用されます。 xの個別値が多い場合、インデックス全体のスキャンが必要になる状況になりうるため、ほとんどの場合プランナはインデックスを使用するよりもシーケンシャルスキャンを好みます。

The skip scan optimization can also be applied selectively, during B-tree scans that have at least some useful constraints from the query predicate. For example, given an index on <literal>(a, b, c)</literal> and a query condition <literal>WHERE a = 5 AND b &gt;= 42 AND c &lt; 77</literal>, the index might have to be scanned from the first entry with <literal>a</literal> = 5 and <literal>b</literal> = 42 up through the last entry with <literal>a</literal> = 5. Index entries with <literal>c</literal> &gt;= 77 will never need to be filtered at the table level, but it may or may not be profitable to skip over them within the index. When skipping takes place, the scan starts a new index search to reposition itself from the end of the current <literal>a</literal> = 5 and <literal>b</literal> = N grouping (i.e. from the position in the index where the first tuple <literal>a = 5 AND b = N AND c &gt;= 77</literal> appears), to the start of the next such grouping (i.e. the position in the index where the first tuple <literal>a = 5 AND b = N + 1</literal> appears). スキップスキャンの最適化は、問い合わせの述語に有用な制約が少なくともいくつかあるB-treeスキャン中に、選択的に適用することもできます。 たとえば、(a, b, c)にインデックスがあり、WHERE a = 5 AND b >= 42 AND c < 77という問い合わせ条件がある場合、インデックスはa = 5およびb = 42の最初のエントリからa = 5の最後のエントリまでスキャンする必要があるかもしれません。 c >= 77のインデックスエントリはテーブルレベルでフィルタリングする必要はありませんが、インデックス内でスキップすると効果がある場合とない場合があります。 スキップが行われると、スキャンは新しいインデックス検索を開始し、現在のa = 5とb = Nのグループの末尾(つまり、a = 5 AND b = N AND c >= 77の最初のタプルが現れるインデックスの位置)から、次のグルーピングの開始位置(つまり、a = 5 AND b = N + 1の最初のタプルが現れるインデックスの位置)まで位置を変更します。

A multicolumn GiST index can be used with query conditions that involve any subset of the index's columns. Conditions on additional columns restrict the entries returned by the index, but the condition on the first column is the most important one for determining how much of the index needs to be scanned. A GiST index will be relatively ineffective if its first column has only a few distinct values, even if there are many distinct values in additional columns. 複数列GiSTインデックスは、インデックス対象列の任意の部分集合を含む問い合わせ条件で使用することができます。 他の列に対する条件は、インデックスで返される項目を制限します。 しかし、先頭列に対する条件が、インデックスのスキャン量を決定するもっとも重要なものです。 先頭列の個別値がわずかな場合、他の列が多くの個別値を持っていたとしても、相対的にGiSTインデックスは非効率的になります。

A multicolumn GIN index can be used with query conditions that involve any subset of the index's columns. Unlike B-tree or GiST, index search effectiveness is the same regardless of which index column(s) the query conditions use. 複数列GINインデックスは、インデックス対象列の任意の部分集合を含む問い合わせ条件で使用することができます。 B-treeやGiSTと異なり、インデックス検索の効果はどのインデックス列が問い合わせ条件で使用されているかに関係なく同じです。

A multicolumn BRIN index can be used with query conditions that involve any subset of the index's columns. Like GIN and unlike B-tree or GiST, index search effectiveness is the same regardless of which index column(s) the query conditions use. The only reason to have multiple BRIN indexes instead of one multicolumn BRIN index on a single table is to have a different <literal>pages_per_range</literal> storage parameter. 複数列BRINインデックスは、インデックス対象列の任意の部分集合を含む問い合わせ条件で使用することができます。 GINと同様に、またB-treeやGiSTとは異なり、インデックス検索の効果はどのインデックス列が問い合わせ条件で使用されているかに関係なく同じです。 一つのテーブルに対して複数列BRINインデックスを一つ持つ代わりに複数のBRINインデックスを持つ唯一の理由は、異なるpages_per_rangeストレージパラメータを持つためです。

Of course, each column must be used with operators appropriate to the index type; clauses that involve other operators will not be considered. 当然ながら、インデックス種類に対して適切な演算子を各列に使用しなければなりません。 他の演算子を含む句は考慮されません。

Multicolumn indexes should be used sparingly. In most situations, an index on a single column is sufficient and saves space and time. Indexes with more than three columns are unlikely to be helpful unless the usage of the table is extremely stylized. See also <xref linkend="indexes-bitmap-scans"/> and <xref linkend="indexes-index-only-scans"/> for some discussion of the merits of different index configurations. 複数列インデックスは慎重に使用する必要があります。 多くの場合、単一列のインデックスで十分であり、また、その方がディスク領域と時間を節約できます。 テーブルの使用方法が極端に様式化されていない限り、4つ以上の列を使用しているインデックスは、不適切である可能性が高いでしょう。 異なるインデックス構成の利点に関するこの他の説明について11.5および11.9も参照してください。