Home Explore Blog CI



postgresql

10th chunk of `doc/src/sgml/perform.sgml`
8c689d6d0b8ea2ec8c7d3f214a84ae24da36bbc9422690840000000100000fa1
 t.ten < ALL (SELECT o.ten FROM onek o WHERE o.four = t.four);

                               QUERY PLAN
-------------------------------------------------------------------&zwsp;------
 Seq Scan on public.tenk1 t  (cost=0.00..586095.00 rows=5000 width=4)
   Output: t.unique1
   Filter: (ALL (t.ten < (SubPlan 1).col1))
   SubPlan 1
     ->  Seq Scan on public.onek o  (cost=0.00..116.50 rows=250 width=4)
           Output: o.ten
           Filter: (o.four = t.four)
</screen>

    This rather artificial example serves to illustrate a couple of
    points: values from the outer plan level can be passed down into a
    subplan (here, <literal>t.four</literal> is passed down) and the
    results of the sub-select are available to the outer plan.  Those
    result values are shown by <command>EXPLAIN</command> with notations
    like
    <literal>(<replaceable>subplan_name</replaceable>).col<replaceable>N</replaceable></literal>,
    which refers to the <replaceable>N</replaceable>'th output column of
    the sub-<literal>SELECT</literal>.
   </para>

   <para>
    <indexterm>
     <primary>subplan</primary>
     <secondary>hashed</secondary>
    </indexterm>
    In the example above, the <literal>ALL</literal> operator runs the
    subplan again for each row of the outer query (which accounts for the
    high estimated cost).  Some queries can use a <firstterm>hashed
    subplan</firstterm> to avoid that:

<screen>
EXPLAIN SELECT *
FROM tenk1 t
WHERE t.unique1 NOT IN (SELECT o.unique1 FROM onek o);

                                         QUERY PLAN
-------------------------------------------------------------------&zwsp;-------------------------
 Seq Scan on tenk1 t  (cost=61.77..531.77 rows=5000 width=244)
   Filter: (NOT (ANY (unique1 = (hashed SubPlan 1).col1)))
   SubPlan 1
     -&gt;  Index Only Scan using onek_unique1 on onek o  (cost=0.28..59.27 rows=1000 width=4)
(4 rows)
</screen>

    Here, the subplan is run a single time and its output is loaded into
    an in-memory hash table, which is then probed by the
    outer <literal>ANY</literal> operator.  This requires that the
    sub-<literal>SELECT</literal> not reference any variables of the outer
    query, and that the <literal>ANY</literal>'s comparison operator be
    amenable to hashing.
   </para>

   <para>
    <indexterm>
     <primary>initplan</primary>
    </indexterm>
    If, in addition to not referencing any variables of the outer query,
    the sub-<literal>SELECT</literal> cannot return more than one row,
    it may instead be implemented as an <firstterm>initplan</firstterm>:

<screen>
EXPLAIN VERBOSE SELECT unique1
FROM tenk1 t1 WHERE t1.ten = (SELECT (random() * 10)::integer);

                             QUERY PLAN
------------------------------------------------------------&zwsp;--------
 Seq Scan on public.tenk1 t1  (cost=0.02..470.02 rows=1000 width=4)
   Output: t1.unique1
   Filter: (t1.ten = (InitPlan 1).col1)
   InitPlan 1
     -&gt;  Result  (cost=0.00..0.02 rows=1 width=4)
           Output: ((random() * '10'::double precision))::integer
</screen>

    An initplan is run only once per execution of the outer plan, and its
    results are saved for re-use in later rows of the outer plan.  So in
    this example <literal>random()</literal> is evaluated only once and
    all the values of <literal>t1.ten</literal> are compared to the same
    randomly-chosen integer.  That's quite different from what would
    happen without the sub-<literal>SELECT</literal> construct.
   </para>

  </sect2>

  <sect2 id="using-explain-analyze">
   <title><command>EXPLAIN ANALYZE</command></title>

   <para>
    It is possible to check the accuracy of the planner's estimates
    by using <command>EXPLAIN</command>'s <literal>ANALYZE</literal> option.  With this
    option, <command>EXPLAIN</command> actually executes the query, and then displays
    the true row counts and true run time accumulated within each plan node,
    along with the same estimates

Title: Subplans, Hashed Subplans, and Initplans in Query Planning
Summary
This section explains how subplans, hashed subplans, and initplans work in query planning, including how values from the outer plan can be passed down into a subplan, how subplans can be run multiple times or hashed for efficiency, and how initplans can be used for sub-SELECTs that return only one row, with examples illustrating the differences in query plans and execution.