]> granicus.if.org Git - postgresql/commitdiff
Improve user-facing documentation for partial/parallel aggregation.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 22 Jun 2016 23:14:16 +0000 (19:14 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 22 Jun 2016 23:14:16 +0000 (19:14 -0400)
Add a section to xaggr.sgml, as we have done in the past for other
extensions to the aggregation functionality.  Assorted wordsmithing
and other minor improvements.

David Rowley and Tom Lane

doc/src/sgml/ref/create_aggregate.sgml
doc/src/sgml/xaggr.sgml

index 6dc193199793d5322a951cdb7647dc67b3a50a0e..6a8acfb4f9ce2c396e386f9ca2dfbe07e142d1f4 100644 (file)
@@ -50,9 +50,8 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ [ <replac
     [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
     [ , FINALFUNC_EXTRA ]
     [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
-    [ , HYPOTHETICAL ]
     [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]
-
+    [ , HYPOTHETICAL ]
 )
 
 <phrase>or the old syntax</phrase>
@@ -221,6 +220,17 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
    aggregate-input rows as an additional <quote>hypothetical</> row.
   </para>
 
+  <para>
+   An aggregate can optionally support <firstterm>partial aggregation</>,
+   as described in <xref linkend="xaggr-partial-aggregates">.
+   This requires specifying the <literal>COMBINEFUNC</> parameter.
+   If the <replaceable class="PARAMETER">state_data_type</replaceable>
+   is <type>internal</>, it's usually also appropriate to provide the
+   <literal>SERIALFUNC</> and <literal>DESERIALFUNC</> parameters so that
+   parallel aggregation is possible.  Note that the aggregate must also be
+   marked <literal>PARALLEL SAFE</> to enable parallel aggregation.
+  </para>
+
   <para>
    Aggregates that behave like <function>MIN</> or <function>MAX</> can
    sometimes be optimized by looking into an index instead of scanning every
@@ -408,12 +418,7 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
      <para>
       The <replaceable class="PARAMETER">combinefunc</replaceable> function
       may optionally be specified to allow the aggregate function to support
-      partial aggregation. This is a prerequisite to allow the aggregate to
-      participate in certain optimizations such as parallel aggregation.
-     </para>
-
-     <para>
-      If provided,
+      partial aggregation.  If provided,
       the <replaceable class="PARAMETER">combinefunc</replaceable> must
       combine two <replaceable class="PARAMETER">state_data_type</replaceable>
       values, each containing the result of aggregation over some subset of
@@ -422,20 +427,15 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
       represents the result of aggregating over both sets of inputs.  This
       function can be thought of as
       an <replaceable class="PARAMETER">sfunc</replaceable>, where instead of
-      acting upon individual input rows and adding these to the aggregate
-      state, it adds another aggregate state to the aggregate state.
-      Typically, it is not possible to define
-      a <replaceable class="PARAMETER">combinefunc</replaceable> for aggregate
-      functions that are sensitive to the order of the input values, since the
-      relative ordering of the inputs that went into the subset states is
-      indeterminate.
+      acting upon an individual input row and adding it to the running
+      aggregate state, it adds another aggregate state to the running state.
      </para>
 
      <para>
-      The <replaceable class="PARAMETER">combinefunc</replaceable> must accept
-      two arguments of
+      The <replaceable class="PARAMETER">combinefunc</replaceable> must be
+      declared as taking two arguments of
       the <replaceable class="PARAMETER">state_data_type</replaceable> and
-      return a value of
+      returning a value of
       the <replaceable class="PARAMETER">state_data_type</replaceable>.
       Optionally this function may be <quote>strict</quote>. In this case the
       function will not be called when either of the input states are null;
@@ -446,11 +446,11 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
       For aggregate functions
       whose <replaceable class="PARAMETER">state_data_type</replaceable>
       is <type>internal</type>,
-      the <replaceable class="PARAMETER">combinefunc</replaceable> must not be
-      strict. In this scenario
-      the <replaceable class="PARAMETER">combinefunc</replaceable> must ensure
-      that null states are handled correctly and that the state being returned
-      is properly stored in the aggregate memory context.
+      the <replaceable class="PARAMETER">combinefunc</replaceable> must not
+      be strict. In this case
+      the <replaceable class="PARAMETER">combinefunc</replaceable> must
+      ensure that null states are handled correctly and that the state being
+      returned is properly stored in the aggregate memory context.
      </para>
     </listitem>
    </varlistentry>
@@ -586,6 +586,22 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>PARALLEL</literal></term>
+    <listitem>
+     <para>
+      The meanings of <literal>PARALLEL SAFE</>, <literal>PARALLEL
+      RESTRICTED</>, and <literal>PARALLEL UNSAFE</> are the same as
+      for <xref linkend="sql-createfunction">.  An aggregate will not be
+      considered for parallelization if it is marked <literal>PARALLEL
+      UNSAFE</> (which is the default!) or <literal>PARALLEL RESTRICTED</>.
+      Note that the parallel-safety markings of the aggregate's support
+      functions are not consulted by the planner, only the marking of the
+      aggregate itself.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>HYPOTHETICAL</literal></term>
     <listitem>
@@ -686,10 +702,11 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
    </para>
 
    <para>
-    The meaning of <literal>PARALLEL SAFE</>, <literal>PARALLEL RESTRICTED</>,
-    and <literal>PARALLEL UNSAFE</> is the same as for
-    <xref linkend="sql-createfunction">.
-   </para>
+    Partial (including parallel) aggregation is currently not supported for
+    ordered-set aggregates.  Also, it will never be used for aggregate calls
+    that include <literal>DISTINCT</> or <literal>ORDER BY</> clauses, since
+    those semantics cannot be supported during partial aggregation.
+  </para>
  </refsect1>
 
  <refsect1>
index ef7cff487949b016b071553de5209a712fdd0455..fa98572ed67b7e3f4bf89cd3c01c248a07a4f165 100644 (file)
@@ -23,7 +23,7 @@
    A <firstterm>final function</firstterm>
    can also be specified, in case the desired result of the aggregate
    is different from the data that needs to be kept in the running
-   state value.  The final function takes the last state value
+   state value.  The final function takes the ending state value
    and returns whatever is wanted as the aggregate result.
    In principle, the transition and final functions are just ordinary
    functions that could also be used outside the context of the
@@ -509,6 +509,102 @@ SELECT percentile_disc(0.5) WITHIN GROUP (ORDER BY income) FROM households;
    and therefore there is no need for them to support moving-aggregate mode.
   </para>
 
+ </sect2>
+
+  <sect2 id="xaggr-partial-aggregates">
+  <title>Partial Aggregation</title>
+
+  <indexterm>
+   <primary>aggregate function</primary>
+   <secondary>partial aggregation</secondary>
+  </indexterm>
+
+  <para>
+   Optionally, an aggregate function can support <firstterm>partial
+   aggregation</>.  The idea of partial aggregation is to run the aggregate's
+   state transition function over different subsets of the input data
+   independently, and then to combine the state values resulting from those
+   subsets to produce the same state value that would have resulted from
+   scanning all the input in a single operation.  This mode can be used for
+   parallel aggregation by having different worker processes scan different
+   portions of a table.  Each worker produces a partial state value, and at
+   the end those state values are combined to produce a final state value.
+   (In the future this mode might also be used for purposes such as combining
+   aggregations over local and remote tables; but that is not implemented
+   yet.)
+  </para>
+
+  <para>
+   To support partial aggregation, the aggregate definition must provide
+   a <firstterm>combine function</>, which takes two values of the
+   aggregate's state type (representing the results of aggregating over two
+   subsets of the input rows) and produces a new value of the state type,
+   representing what the state would have been after aggregating over the
+   combination of those sets of rows.  It is unspecified what the relative
+   order of the input rows from the two sets would have been.  This means
+   that it's usually impossible to define a useful combine function for
+   aggregates that are sensitive to input row order.
+  </para>
+
+  <para>
+   As simple examples, <literal>MAX</> and <literal>MIN</> aggregates can be
+   made to support partial aggregation by specifying the combine function as
+   the same greater-of-two or lesser-of-two comparison function that is used
+   as their transition function.  <literal>SUM</> aggregates just need an
+   addition function as combine function.  (Again, this is the same as their
+   transition function, unless the state value is wider than the input data
+   type.)
+  </para>
+
+  <para>
+   The combine function is treated much like a transition function that
+   happens to take a value of the state type, not of the underlying input
+   type, as its second argument.  In particular, the rules for dealing
+   with null values and strict functions are similar.  Also, if the aggregate
+   definition specifies a non-null <literal>initcond</>, keep in mind that
+   that will be used not only as the initial state for each partial
+   aggregation run, but also as the initial state for the combine function,
+   which will be called to combine each partial result into that state.
+  </para>
+
+  <para>
+   If the aggregate's state type is declared as <type>internal</>, it is
+   the combine function's responsibility that its result is allocated in
+   the correct memory context for aggregate state values.  This means in
+   particular that when the first input is <literal>NULL</> it's invalid
+   to simply return the second input, as that value will be in the wrong
+   context and will not have sufficient lifespan.
+  </para>
+
+  <para>
+   When the aggregate's state type is declared as <type>internal</>, it is
+   usually also appropriate for the aggregate definition to provide a
+   <firstterm>serialization function</> and a <firstterm>deserialization
+   function</>, which allow such a state value to be copied from one process
+   to another.  Without these functions, parallel aggregation cannot be
+   performed, and future applications such as local/remote aggregation will
+   probably not work either.
+  </para>
+
+  <para>
+   A serialization function must take a single argument of
+   type <type>internal</> and return a result of type <type>bytea</>, which
+   represents the state value packaged up into a flat blob of bytes.
+   Conversely, a deserialization function reverses that conversion.  It must
+   take two arguments of types <type>bytea</> and <type>internal</>, and
+   return a result of type <type>internal</>.  (The second argument is unused
+   and is always zero, but it is required for type-safety reasons.)  The
+   result of the deserialization function should simply be allocated in the
+   current memory context, as unlike the combine function's result, it is not
+   long-lived.
+  </para>
+
+  <para>
+   Worth noting also is that for an aggregate to be executed in parallel,
+   the aggregate itself must be marked <literal>PARALLEL SAFE</>.  The
+   parallel-safety markings on its support functions are not consulted.
+  </para>
+
  </sect2>
 
  <sect2 id="xaggr-support-functions">
@@ -521,7 +617,7 @@ SELECT percentile_disc(0.5) WITHIN GROUP (ORDER BY income) FROM households;
 
   <para>
    A function written in C can detect that it is being called as an
-   aggregate transition or final function by calling
+   aggregate support function by calling
    <function>AggCheckCallContext</>, for example:
 <programlisting>
 if (AggCheckCallContext(fcinfo, NULL))