default, B-tree indexes store their entries in ascending order
with nulls last (table TID is treated as a tiebreaker column among
otherwise equal entries). This means that a forward scan of an
index on column <literal>x</literal> produces output satisfying <literal>ORDER BY x</literal>
(or more verbosely, <literal>ORDER BY x ASC NULLS LAST</literal>). The
index can also be scanned backward, producing output satisfying
<literal>ORDER BY x DESC</literal>
(or more verbosely, <literal>ORDER BY x DESC NULLS FIRST</literal>, since
<literal>NULLS FIRST</literal> is the default for <literal>ORDER BY DESC</literal>).
</para>
<para>
You can adjust the ordering of a B-tree index by including the
options <literal>ASC</literal>, <literal>DESC</literal>, <literal>NULLS FIRST</literal>,
and/or <literal>NULLS LAST</literal> when creating the index; for example:
<programlisting>
CREATE INDEX test2_info_nulls_low ON test2 (info NULLS FIRST);
CREATE INDEX test3_desc_index ON test3 (id DESC NULLS LAST);
</programlisting>
An index stored in ascending order with nulls first can satisfy
either <literal>ORDER BY x ASC NULLS FIRST</literal> or
<literal>ORDER BY x DESC NULLS LAST</literal> depending on which direction
it is scanned in.
</para>
<para>
You might wonder why bother providing all four options, when two
options together with the possibility of backward scan would cover
all the variants of <literal>ORDER BY</literal>. In single-column indexes
the options are indeed redundant, but in multicolumn indexes they can be
useful. Consider a two-column index on <literal>(x, y)</literal>: this can
satisfy <literal>ORDER BY x, y</literal> if we scan forward, or
<literal>ORDER BY x DESC, y DESC</literal> if we scan backward.
But it might be that the application frequently needs to use
<literal>ORDER BY x ASC, y DESC</literal>. There is no way to get that
ordering from a plain index, but it is possible if the index is defined
as <literal>(x ASC, y DESC)</literal> or <literal>(x DESC, y ASC)</literal>.
</para>
<para>
Obviously, indexes with non-default sort orderings are a fairly
specialized feature, but sometimes they can produce tremendous
speedups for certain queries. Whether it's worth maintaining such an
index depends on how often you use queries that require a special
sort ordering.
</para>
</sect1>
<sect1 id="indexes-bitmap-scans">
<title>Combining Multiple Indexes</title>
<indexterm zone="indexes-bitmap-scans">
<primary>index</primary>
<secondary>combining multiple indexes</secondary>
</indexterm>
<indexterm zone="indexes-bitmap-scans">
<primary>bitmap scan</primary>
</indexterm>
<para>
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.
</para>
<para>
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>