</programlisting>
This is a bad idea! Almost certainly, you'll be better off with a
single non-partial index, declared like
<programlisting>
CREATE INDEX mytable_cat_data ON mytable (category, data);
</programlisting>
(Put the category column first, for the reasons described in
<xref linkend="indexes-multicolumn"/>.) While a search in this larger
index might have to descend through a couple more tree levels than a
search in a smaller index, that's almost certainly going to be cheaper
than the planner effort needed to select the appropriate one of the
partial indexes. The core of the problem is that the system does not
understand the relationship among the partial indexes, and will
laboriously test each one to see if it's applicable to the current
query.
</para>
<para>
If your table is large enough that a single index really is a bad idea,
you should look into using partitioning instead (see
<xref linkend="ddl-partitioning"/>). With that mechanism, the system
does understand that the tables and indexes are non-overlapping, so
far better performance is possible.
</para>
</example>
<para>
More information about partial indexes can be found in <xref
linkend="ston89b"/>, <xref linkend="olson93"/>, and <xref
linkend="seshadri95"/>.
</para>
</sect1>
<sect1 id="indexes-index-only-scans">
<title>Index-Only Scans and Covering Indexes</title>
<indexterm zone="indexes-index-only-scans">
<primary>index</primary>
<secondary>index-only scans</secondary>
</indexterm>
<indexterm zone="indexes-index-only-scans">
<primary>index-only scan</primary>
</indexterm>
<indexterm zone="indexes-index-only-scans">
<primary>index</primary>
<secondary>covering</secondary>
</indexterm>
<indexterm zone="indexes-index-only-scans">
<primary>covering index</primary>
</indexterm>
<para>
All indexes in <productname>PostgreSQL</productname>
are <firstterm>secondary</firstterm> indexes, meaning that each index is
stored separately from the table's main data area (which is called the
table's <firstterm>heap</firstterm>
in <productname>PostgreSQL</productname> terminology). This means that
in an ordinary index scan, each row retrieval requires fetching data from
both the index and the heap. Furthermore, while the index entries that
match a given indexable <literal>WHERE</literal> condition are usually
close together in the index, the table rows they reference might be
anywhere in the heap. The heap-access portion of an index scan thus
involves a lot of random access into the heap, which can be slow,
particularly on traditional rotating media. (As described in
<xref linkend="indexes-bitmap-scans"/>, bitmap scans try to alleviate
this cost by doing the heap accesses in sorted order, but that only goes
so far.)
</para>
<para>
To solve this performance problem, <productname>PostgreSQL</productname>
supports <firstterm>index-only scans</firstterm>, which can answer
queries from an index alone without any heap access. The basic idea is
to return values directly out of each index entry instead of consulting
the associated heap entry. There are two fundamental restrictions on
when this method can be used:
<orderedlist>
<listitem>
<para>
The index type must support index-only scans. B-tree indexes always
do. GiST and SP-GiST indexes support index-only scans for some
operator classes but not others. Other index types have no support.
The underlying requirement is that the index must physically store, or
else be able to reconstruct, the original data value for each index
entry. As a counterexample, GIN indexes cannot support index-only
scans because each index entry typically holds only part of the
original data value.
</para>
</listitem>
<listitem>
<para>
The query must reference