Home Explore Blog CI



postgresql

16th chunk of `doc/src/sgml/indices.sgml`
71fca8da47266219577df87b764981ad175726840b3bd0db0000000100000fa1

</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

Title: Partial Indexes: Avoiding Misuse and Introduction to Index-Only Scans
Summary
Using a large set of non-overlapping partial indexes is generally a bad idea. A single non-partial index is usually more efficient because the system struggles to understand the relationships between partial indexes, leading to increased planner effort. If a single index is too large, consider using table partitioning instead. The section then transitions to discussing index-only scans, where PostgreSQL can answer queries using only the index data, avoiding the need to access the table's heap. This optimization requires the index type to support it (B-tree indexes always do) and the query must only reference data stored within the index.