Home Explore Blog CI



postgresql

4th chunk of `doc/src/sgml/perform.sgml`
ec01a9a8a38c1d9cb38d454c5e75a481d1e96cfa8d6ab1f50000000100000fb7
 <command>ANALYZE</command> command, because the
    statistics produced by <command>ANALYZE</command> are taken from a
    randomized sample of the table.
   </para>

   <para>
    Now, let's make the condition more restrictive:

<screen>
EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 100;

                                  QUERY PLAN
-------------------------------------------------------------------&zwsp;-----------
 Bitmap Heap Scan on tenk1  (cost=5.06..224.98 rows=100 width=244)
   Recheck Cond: (unique1 &lt; 100)
   -&gt;  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.04 rows=100 width=0)
         Index Cond: (unique1 &lt; 100)
</screen>

    Here the planner has decided to use a two-step plan: the child plan
    node visits an index to find the locations of rows matching the index
    condition, and then the upper plan node actually fetches those rows
    from the table itself.  Fetching rows separately is much more
    expensive than reading them sequentially, but because not all the pages
    of the table have to be visited, this is still cheaper than a sequential
    scan.  (The reason for using two plan levels is that the upper plan
    node sorts the row locations identified by the index into physical order
    before reading them, to minimize the cost of separate fetches.
    The <quote>bitmap</quote> mentioned in the node names is the mechanism that
    does the sorting.)
   </para>

   <para>
    Now let's add another condition to the <literal>WHERE</literal> clause:

<screen>
EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 100 AND stringu1 = 'xxx';

                                  QUERY PLAN
-------------------------------------------------------------------&zwsp;-----------
 Bitmap Heap Scan on tenk1  (cost=5.04..225.20 rows=1 width=244)
   Recheck Cond: (unique1 &lt; 100)
   Filter: (stringu1 = 'xxx'::name)
   -&gt;  Bitmap Index Scan on tenk1_unique1  (cost=0.00..5.04 rows=100 width=0)
         Index Cond: (unique1 &lt; 100)
</screen>

    The added condition <literal>stringu1 = 'xxx'</literal> reduces the
    output row count estimate, but not the cost because we still have to visit
    the same set of rows.  That's because the <literal>stringu1</literal> clause
    cannot be applied as an index condition, since this index is only on
    the <literal>unique1</literal> column.  Instead it is applied as a filter on
    the rows retrieved using the index.  Thus the cost has actually gone up
    slightly to reflect this extra checking.
   </para>

   <para>
    In some cases the planner will prefer a <quote>simple</quote> index scan plan:

<screen>
EXPLAIN SELECT * FROM tenk1 WHERE unique1 = 42;

                                 QUERY PLAN
-------------------------------------------------------------------&zwsp;----------
 Index Scan using tenk1_unique1 on tenk1  (cost=0.29..8.30 rows=1 width=244)
   Index Cond: (unique1 = 42)
</screen>

    In this type of plan the table rows are fetched in index order, which
    makes them even more expensive to read, but there are so few that the
    extra cost of sorting the row locations is not worth it.  You'll most
    often see this plan type for queries that fetch just a single row.  It's
    also often used for queries that have an <literal>ORDER BY</literal> condition
    that matches the index order, because then no extra sorting step is needed
    to satisfy the <literal>ORDER BY</literal>.  In this example, adding
    <literal>ORDER BY unique1</literal> would use the same plan because the
    index already implicitly provides the requested ordering.
   </para>

   <para>
     The planner may implement an <literal>ORDER BY</literal> clause in several
     ways.  The above example shows that such an ordering clause may be
     implemented implicitly.  The planner may also add an explicit
     <literal>Sort</literal> step:

<screen>
EXPLAIN SELECT * FROM tenk1 ORDER BY unique1;

                            QUERY PLAN
-------------------------------------------------------------------

Title: Query Planning with Indexes and Ordering
Summary
This section explains how the planner chooses between different query plans, including when to use indexes, bitmap scans, and sort operations, and how the planner optimizes queries with WHERE and ORDER BY clauses, using examples to illustrate the decision-making process and the resulting query plans.