A single index scan can only use query clauses that use the index's
columns with operators of its operator class and are joined with
<literal>AND</literal>. For example, given an index on <literal>(a, b)</literal>
a query condition like <literal>WHERE a = 5 AND b = 6</literal> could
use the index, but a query like <literal>WHERE a = 5 OR b = 6</literal> could not
directly use the index.
単一のインデックススキャンは、インデックスの列をその演算子クラスの演算子で使用する問い合わせ句と、それをAND
結合したものでのみ使用されます。
例えば、(a, b)
というインデックスとWHERE a = 5 AND b = 6
という問い合わせでは、インデックスが使用されます。
しかし、WHERE a = 5 OR b = 6
のような問い合わせではインデックスは直接使用されません。
Fortunately,
<productname>PostgreSQL</productname> has the ability to combine multiple indexes
(including multiple uses of the same index) to handle cases that cannot
be implemented by single index scans. The system can form <literal>AND</literal>
and <literal>OR</literal> conditions across several index scans. For example,
a query like <literal>WHERE x = 42 OR x = 47 OR x = 53 OR x = 99</literal>
could be broken down into four separate scans of an index on <literal>x</literal>,
each scan using one of the query clauses. The results of these scans are
then ORed together to produce the result. Another example is that if we
have separate indexes on <literal>x</literal> and <literal>y</literal>, one possible
implementation of a query like <literal>WHERE x = 5 AND y = 6</literal> is to
use each index with the appropriate query clause and then AND together
the index results to identify the result rows.
幸いにも、PostgreSQLは、単一のインデックススキャンでは実装できない場合を扱うために、複数のインデックス(同じインデックスの複数回使用を含む)を組み合わせる機能を持ちます。
システムは複数のインデックススキャンを跨がる、AND
条件およびOR
条件を形成できます。
例えば、
WHERE x = 42 OR x = 47 OR x = 53 OR x = 99
という問い合わせは、問い合わせ句の1つを使用してx
上のインデックスをスキャンする4つのスキャンに分割することができます。
その後、これらのスキャンの結果はOR演算でまとめられ、結果を生成します。
他の例としてx
とy
に別個のインデックスがある場合を考えます。
WHERE x = 5 AND y = 6
のような問い合わせに対して取り得る実装は、適切な問い合わせ句で各インデックスを使用し、インデックスの結果をANDでまとめ、結果行を識別することです。
To combine multiple indexes, the system scans each needed index and
prepares a <firstterm>bitmap</firstterm> in memory giving the locations of
table rows that are reported as matching that index's conditions.
The bitmaps are then ANDed and ORed together as needed by the query.
Finally, the actual table rows are visited and returned. The table rows
are visited in physical order, because that is how the bitmap is laid
out; this means that any ordering of the original indexes is lost, and
so a separate sort step will be needed if the query has an <literal>ORDER
BY</literal> clause. For this reason, and because each additional index scan
adds extra time, the planner will sometimes choose to use a simple index
scan even though additional indexes are available that could have been
used as well.
複数のインデックスを組み合わせるために、システムは必要なインデックスそれぞれをスキャンし、インデックス条件に適合するものと報告されたテーブル行の位置を与えるためにメモリ上にビットマップを準備します。
その後、このビットマップは問い合わせで必要とされたように、ANDまたはOR演算されます。
最後に、実際のテーブル行がアクセスされ、返されます。
テーブル行は物理的な順番でアクセスされます。
ビットマップにこの順番で格納されているからです。
これは、元のインデックスの順序が失われていることを意味します。
そのため、もし問い合わせがORDER BY
句を持つ場合、この他のソート手続きが必要となります。
この理由、および、追加のインデックススキャンそれぞれのために余計な時間が加わることから、プランナは追加のインデックスが同様に使用できる場合であっても、単純なインデックススキャンを選択することがあります。
In all but the simplest applications, there are various combinations of
indexes that might be useful, and the database developer must make
trade-offs to decide which indexes to provide. Sometimes multicolumn
indexes are best, but sometimes it's better to create separate indexes
and rely on the index-combination feature. For example, if your
workload includes a mix of queries that sometimes involve only column
<literal>x</literal>, sometimes only column <literal>y</literal>, and sometimes both
columns, you might choose to create two separate indexes on
<literal>x</literal> and <literal>y</literal>, relying on index combination to
process the queries that use both columns. You could also create a
multicolumn index on <literal>(x, y)</literal>. This index would typically be
more efficient than index combination for queries involving both
columns, but as discussed in <xref linkend="indexes-multicolumn"/>, it
would be almost useless for queries involving only <literal>y</literal>, so it
should not be the only index. A combination of the multicolumn index
and a separate index on <literal>y</literal> would serve reasonably well. For
queries involving only <literal>x</literal>, the multicolumn index could be
used, though it would be larger and hence slower than an index on
<literal>x</literal> alone. The last alternative is to create all three
indexes, but this is probably only reasonable if the table is searched
much more often than it is updated and all three types of query are
common. If one of the types of query is much less common than the
others, you'd probably settle for creating just the two indexes that
best match the common types.
もっとも単純なアプリケーション以外のほとんどすべてのアプリケーションでは、インデックスの有用な組み合わせはいろいろあります。
このため、データベース開発者は妥協点を探してどのようなインデックスを提供するかを決定しなければなりません。
複数列インデックスが最善な場合がありますし、別々のインデックスを作成し、インデックスの組み合わせ機能に依存する方が優れている場合もあります。
例えば、作業にx
列のみを含む場合とy
列のみを含む場合、両方の列を含む場合が混在する問い合わせが含まれる場合、x
とy
に対し、別個に2つのインデックスを作成し、両方の列を使用する問い合わせを処理する時にインデックスの組み合わせに依存することを選ぶことができます。
また、(x, y)
に対する複数列インデックスを作成することもできます。
両方の列を含む問い合わせでは、通常このインデックスの方がインデックスの組み合わせよりも効率的です。
しかし、11.3で説明した通り、y
のみを含む問い合わせではほとんど意味がありません。
従って、このインデックスのみとすることはできません。
複数列インデックスとy
に対する別のインデックスの組み合わせがかなりよく役に立ちます。
x
のみを含む問い合わせでは、複数列インデックスを使用することができます。
しかし、これはより大きくなりますので、x
のみインデックスよりも低速になります。
最後の別方法は、3つのインデックスすべてを作成することです。
しかしこれはおそらく、テーブルの検索頻度が更新頻度よりもかなり高く、3種類の問い合わせすべてが良く使用される場合のみ合理的です。
問い合わせの中の1つの頻度が他よりも少なければ、おそらく良く使用される種類にもっとも合うように2つだけインデックスを作成した方がよいでしょう。