Home Explore Blog CI



postgresql

15th chunk of `doc/src/sgml/indices.sgml`
27ff5f07b5f47d490efb511f244a5dfcb227764cb76969130000000100000fbe
 values of the parameter.
  </para>

  <para>
   A third possible use for partial indexes does not require the
   index to be used in queries at all.  The idea here is to create
   a unique index over a subset of a table, as in <xref
   linkend="indexes-partial-ex3"/>.  This enforces uniqueness
   among the rows that satisfy the index predicate, without constraining
   those that do not.
  </para>

  <example id="indexes-partial-ex3">
   <title>Setting up a Partial Unique Index</title>

   <para>
    Suppose that we have a table describing test outcomes.  We wish
    to ensure that there is only one <quote>successful</quote> entry for
    a given subject and target combination, but there might be any number of
    <quote>unsuccessful</quote> entries.  Here is one way to do it:
<programlisting>
CREATE TABLE tests (
    subject text,
    target text,
    success boolean,
    ...
);

CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target)
    WHERE success;
</programlisting>
    This is a particularly efficient approach when there are few
    successful tests and many unsuccessful ones.  It is also possible to
    allow only one null in a column by creating a unique partial index
    with an <literal>IS NULL</literal> restriction.
   </para>

  </example>

  <para>
   Finally, a partial index can also be used to override the system's
   query plan choices.  Also, data sets with peculiar
   distributions might cause the system to use an index when it really
   should not.  In that case the index can be set up so that it is not
   available for the offending query.  Normally,
   <productname>PostgreSQL</productname> makes reasonable choices about index
   usage (e.g., it avoids them when retrieving common values, so the
   earlier example really only saves index size, it is not required to
   avoid index usage), and grossly incorrect plan choices are cause
   for a bug report.
  </para>

  <para>
   Keep in mind that setting up a partial index indicates that you
   know at least as much as the query planner knows, in particular you
   know when an index might be profitable.  Forming this knowledge
   requires experience and understanding of how indexes in
   <productname>PostgreSQL</productname> work.  In most cases, the
   advantage of a partial index over a regular index will be minimal.
   There are cases where they are quite counterproductive, as in <xref
   linkend="indexes-partial-ex4"/>.
  </para>

  <example id="indexes-partial-ex4">
   <title>Do Not Use Partial Indexes as a Substitute for Partitioning</title>

   <para>
    You might be tempted to create a large set of non-overlapping partial
    indexes, for example

<programlisting>
CREATE INDEX mytable_cat_1 ON mytable (data) WHERE category = 1;
CREATE INDEX mytable_cat_2 ON mytable (data) WHERE category = 2;
CREATE INDEX mytable_cat_3 ON mytable (data) WHERE category = 3;
...
CREATE INDEX mytable_cat_<replaceable>N</replaceable> ON mytable (data) WHERE category = <replaceable>N</replaceable>;
</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"/>).

Title: Partial Indexes: Unique Partial Indexes, Overriding Query Plans, and Avoiding Misuse
Summary
Partial indexes can be used to create unique constraints over a subset of a table, such as allowing only one 'successful' entry per subject and target in a test results table. They can also be used to override the query planner's choices in specific scenarios, although PostgreSQL generally makes reasonable decisions. However, setting up a partial index requires expertise and understanding of how indexes work, as they can be counterproductive if misused. Avoid using a large set of non-overlapping partial indexes as a substitute for partitioning, as this can lead to inefficient query planning. If a single index is too large, consider using table partitioning instead.