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).
</para>
<para>
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.
</para>
<para>
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 >= 42 AND c < 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> >= 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 >= 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).
</para>
<para>
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.
</para>
<para>
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.
</para>
<para>
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.
</para>
<para>
Of course, each column must be used with operators appropriate to the index
type; clauses that involve other operators will not be considered.
</para>
<para>
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