Home Explore Blog CI



postgresql

13th chunk of `doc/src/sgml/indices.sgml`
98fdbbb3d8f5babbd8a514137ac76ff505c5f57472c142ff0000000100000fa3

   values.  Since a query searching for a common value (one that
   accounts for more than a few percent of all the table rows) will not
   use the index anyway, there is no point in keeping those rows in the
   index at all.  This reduces the size of the index, which will speed
   up those queries that do use the index.  It will also speed up many table
   update operations because the index does not need to be
   updated in all cases.  <xref linkend="indexes-partial-ex1"/> shows a
   possible application of this idea.
  </para>

  <example id="indexes-partial-ex1">
   <title>Setting up a Partial Index to Exclude Common Values</title>

   <para>
    Suppose you are storing web server access logs in a database.
    Most accesses originate from the IP address range of your organization but
    some are from elsewhere (say, employees on dial-up connections).
    If your searches by IP are primarily for outside accesses,
    you probably do not need to index the IP range that corresponds to your
    organization's subnet.
   </para>

   <para>
    Assume a table like this:
<programlisting>
CREATE TABLE access_log (
    url varchar,
    client_ip inet,
    ...
);
</programlisting>
   </para>

   <para>
    To create a partial index that suits our example, use a command
    such as this:
<programlisting>
CREATE INDEX access_log_client_ip_ix ON access_log (client_ip)
WHERE NOT (client_ip &gt; inet '192.168.100.0' AND
           client_ip &lt; inet '192.168.100.255');
</programlisting>
   </para>

   <para>
    A typical query that can use this index would be:
<programlisting>
SELECT *
FROM access_log
WHERE url = '/index.html' AND client_ip = inet '212.78.10.32';
</programlisting>
    Here the query's IP address is covered by the partial index.  The
    following query cannot use the partial index, as it uses an IP address
    that is excluded from the index:
<programlisting>
SELECT *
FROM access_log
WHERE url = '/index.html' AND client_ip = inet '192.168.100.23';
</programlisting>
   </para>

   <para>
    Observe that this kind of partial index requires that the common
    values be predetermined, so such partial indexes are best used for
    data distributions that do not change.  Such indexes can be recreated
    occasionally to adjust for new data distributions, but this adds
    maintenance effort.
   </para>
  </example>

  <para>
   Another possible use for a partial index is to exclude values from the
   index that the
   typical query workload is not interested in; this is shown in <xref
   linkend="indexes-partial-ex2"/>.  This results in the same
   advantages as listed above, but it prevents the
   <quote>uninteresting</quote> values from being accessed via that
   index, even if an index scan might be profitable in that
   case.  Obviously, setting up partial indexes for this kind of
   scenario will require a lot of care and experimentation.
  </para>

  <example id="indexes-partial-ex2">
   <title>Setting up a Partial Index to Exclude Uninteresting Values</title>

   <para>
    If you have a table that contains both billed and unbilled orders,
    where the unbilled orders take up a small fraction of the total
    table and yet those are the most-accessed rows, you can improve
    performance by creating an index on just the unbilled rows.  The
    command to create the index would look like this:
<programlisting>
CREATE INDEX orders_unbilled_index ON orders (order_nr)
    WHERE billed is not true;
</programlisting>
   </para>

   <para>
    A possible query to use this index would be:
<programlisting>
SELECT * FROM orders WHERE billed is not true AND order_nr &lt; 10000;
</programlisting>
    However, the index can also be used in queries that do not involve
    <structfield>order_nr</structfield> at all, e.g.:
<programlisting>
SELECT * FROM orders WHERE billed is not true AND amount &gt; 5000.00;
</programlisting>
    This is not as efficient as a partial index on the
    <structfield>amount</structfield> column would

Title: Partial Indexes: Excluding Common or Uninteresting Values
Summary
Partial indexes index only a subset of a table, defined by a predicate. This is useful for excluding common values (which queries won't use the index for anyway) or uninteresting values (to prevent them from being accessed via the index). The example provided shows how to create a partial index on a web server access log to exclude accesses originating from the organization's IP range, and then queries can utilize that index. Another example shows how to index only unbilled orders in an 'orders' table, improving performance when accessing those rows.