This supports indexed queries
using these operators:
<synopsis>
< <= = >= >
</synopsis>
The BRIN operator classes included in the standard distribution are
documented in <xref linkend="brin-builtin-opclasses-table"/>.
For more information see <xref linkend="brin"/>.
</para>
</sect2>
</sect1>
<sect1 id="indexes-multicolumn">
<title>Multicolumn Indexes</title>
<indexterm zone="indexes-multicolumn">
<primary>index</primary>
<secondary>multicolumn</secondary>
</indexterm>
<para>
An index can be defined on more than one column of a table. For example, if
you have a table of this form:
<programlisting>
CREATE TABLE test2 (
major int,
minor int,
name varchar
);
</programlisting>
(say, you keep your <filename class="directory">/dev</filename>
directory in a database...) and you frequently issue queries like:
<programlisting>
SELECT name FROM test2 WHERE major = <replaceable>constant</replaceable> AND minor = <replaceable>constant</replaceable>;
</programlisting>
then it might be appropriate to define an index on the columns
<structfield>major</structfield> and
<structfield>minor</structfield> together, e.g.:
<programlisting>
CREATE INDEX test2_mm_idx ON test2 (major, minor);
</programlisting>
</para>
<para>
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>.)
</para>
<para>
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).
</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