aboutsummaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-01-25 22:28:29 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2021-01-25 22:28:29 -0500
commitee895a655ce4341546facd6f23e3e8f2931b96bf (patch)
tree20f37bfe075a30895105a6888113d1677013f5ef /doc/src
parent55ef8555f0c1207bac25050e7297bbb969c84233 (diff)
downloadpostgresql-ee895a655ce4341546facd6f23e3e8f2931b96bf.tar.gz
postgresql-ee895a655ce4341546facd6f23e3e8f2931b96bf.zip
Improve performance of repeated CALLs within plpgsql procedures.
This patch essentially is cleaning up technical debt left behind by the original implementation of plpgsql procedures, particularly commit d92bc83c4. That patch (or more precisely, follow-on patches fixing its worst bugs) forced us to re-plan CALL and DO statements each time through, if we're in a non-atomic context. That wasn't for any fundamental reason, but just because use of a saved plan requires having a ResourceOwner to hold a reference count for the plan, and we had no suitable resowner at hand, nor would the available APIs support using one if we did. While it's not that expensive to create a "plan" for CALL/DO, the cycles do add up in repeated executions. This patch therefore makes the following API changes: * GetCachedPlan/ReleaseCachedPlan are modified to let the caller specify which resowner to use to pin the plan, rather than forcing use of CurrentResourceOwner. * spi.c gains a "SPI_execute_plan_extended" entry point that lets callers say which resowner to use to pin the plan. This borrows the idea of an options struct from the recently added SPI_prepare_extended, hopefully allowing future options to be added without more API breaks. This supersedes SPI_execute_plan_with_paramlist (which I've marked deprecated) as well as SPI_execute_plan_with_receiver (which is new in v14, so I just took it out altogether). * I also took the opportunity to remove the crude hack of letting plpgsql reach into SPI private data structures to mark SPI plans as "no_snapshot". It's better to treat that as an option of SPI_prepare_extended. Now, when running a non-atomic procedure or DO block that contains any CALL or DO commands, plpgsql creates a ResourceOwner that will be used to pin the plans of the CALL/DO commands. (In an atomic context, we just use CurrentResourceOwner, as before.) Having done this, we can just save CALL/DO plans normally, whether or not they are used across transaction boundaries. This seems to be good for something like 2X speedup of a CALL of a trivial procedure with a few simple argument expressions. By restricting the creation of an extra ResourceOwner like this, there's essentially zero penalty in cases that can't benefit. Pavel Stehule, with some further hacking by me Discussion: https://postgr.es/m/CAFj8pRCLPdDAETvR7Po7gC5y_ibkn_-bOzbeJb39WHms01194Q@mail.gmail.com
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/spi.sgml165
1 files changed, 111 insertions, 54 deletions
diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml
index f5e0a35da06..d8c121f5f35 100644
--- a/doc/src/sgml/spi.sgml
+++ b/doc/src/sgml/spi.sgml
@@ -1722,25 +1722,23 @@ int SPI_execute_plan(SPIPlanPtr <parameter>plan</parameter>, Datum * <parameter>
<!-- *********************************************** -->
-<refentry id="spi-spi-execute-plan-with-paramlist">
- <indexterm><primary>SPI_execute_plan_with_paramlist</primary></indexterm>
+<refentry id="spi-spi-execute-plan-extended">
+ <indexterm><primary>SPI_execute_plan_extended</primary></indexterm>
<refmeta>
- <refentrytitle>SPI_execute_plan_with_paramlist</refentrytitle>
+ <refentrytitle>SPI_execute_plan_extended</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
- <refname>SPI_execute_plan_with_paramlist</refname>
+ <refname>SPI_execute_plan_extended</refname>
<refpurpose>execute a statement prepared by <function>SPI_prepare</function></refpurpose>
</refnamediv>
<refsynopsisdiv>
<synopsis>
-int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
- ParamListInfo <parameter>params</parameter>,
- bool <parameter>read_only</parameter>,
- long <parameter>count</parameter>)
+int SPI_execute_plan_extended(SPIPlanPtr <parameter>plan</parameter>,
+ const SPIExecuteOptions * <parameter>options</parameter>)
</synopsis>
</refsynopsisdiv>
@@ -1748,14 +1746,29 @@ int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
<title>Description</title>
<para>
- <function>SPI_execute_plan_with_paramlist</function> executes a statement
- prepared by <function>SPI_prepare</function>.
- This function is equivalent to <function>SPI_execute_plan</function>
+ <function>SPI_execute_plan_extended</function> executes a statement
+ prepared by <function>SPI_prepare</function> or one of its siblings.
+ This function is equivalent to <function>SPI_execute_plan</function>,
except that information about the parameter values to be passed to the
- query is presented differently. The <literal>ParamListInfo</literal>
- representation can be convenient for passing down values that are
- already available in that format. It also supports use of dynamic
- parameter sets via hook functions specified in <literal>ParamListInfo</literal>.
+ query is presented differently, and additional execution-controlling
+ options can be passed.
+ </para>
+
+ <para>
+ Query parameter values are represented by
+ a <literal>ParamListInfo</literal> struct, which is convenient for passing
+ down values that are already available in that format. Dynamic parameter
+ sets can also be used, via hook functions specified
+ in <literal>ParamListInfo</literal>.
+ </para>
+
+ <para>
+ Also, instead of always accumulating the result tuples into a
+ <varname>SPI_tuptable</varname> structure, tuples can be passed to a
+ caller-supplied <literal>DestReceiver</literal> object as they are
+ generated by the executor. This is particularly helpful for queries
+ that might generate many tuples, since the data can be processed
+ on-the-fly instead of being accumulated in memory.
</para>
</refsect1>
@@ -1773,10 +1786,29 @@ int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
</varlistentry>
<varlistentry>
+ <term><literal>const SPIExecuteOptions * <parameter>options</parameter></literal></term>
+ <listitem>
+ <para>
+ struct containing optional arguments
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Callers should always zero out the entire <parameter>options</parameter>
+ struct, then fill whichever fields they want to set. This ensures forward
+ compatibility of code, since any fields that are added to the struct in
+ future will be defined to behave backwards-compatibly if they are zero.
+ The currently available <parameter>options</parameter> fields are:
+ </para>
+
+ <variablelist>
+ <varlistentry>
<term><literal>ParamListInfo <parameter>params</parameter></literal></term>
<listitem>
<para>
- data structure containing parameter types and values; NULL if none
+ data structure containing query parameter types and values; NULL if none
</para>
</listitem>
</varlistentry>
@@ -1789,7 +1821,17 @@ int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
</varlistentry>
<varlistentry>
- <term><literal>long <parameter>count</parameter></literal></term>
+ <term><literal>bool <parameter>no_snapshots</parameter></literal></term>
+ <listitem>
+ <para>
+ <literal>true</literal> prevents SPI from managing snapshots for
+ execution of the query; use with extreme caution
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>uint64 <parameter>tcount</parameter></literal></term>
<listitem>
<para>
maximum number of rows to return,
@@ -1797,6 +1839,29 @@ int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term><literal>DestReceiver * <parameter>dest</parameter></literal></term>
+ <listitem>
+ <para>
+ <literal>DestReceiver</literal> object that will receive any tuples
+ emitted by the query; if NULL, result tuples are accumulated into
+ a <varname>SPI_tuptable</varname> structure, as
+ in <function>SPI_execute_plan</function>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>ResourceOwner <parameter>owner</parameter></literal></term>
+ <listitem>
+ <para>
+ The resource owner that will hold a reference count on the plan while
+ it is executed. If NULL, CurrentResourceOwner is used. Ignored for
+ non-saved plans, as SPI does not acquire reference counts on those.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
@@ -1808,35 +1873,40 @@ int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
</para>
<para>
+ When <parameter>dest</parameter> is NULL,
<varname>SPI_processed</varname> and
<varname>SPI_tuptable</varname> are set as in
- <function>SPI_execute_plan</function> if successful.
+ <function>SPI_execute_plan</function>.
+ When <parameter>dest</parameter> is not NULL,
+ <varname>SPI_processed</varname> is set to zero and
+ <varname>SPI_tuptable</varname> is set to NULL. If a tuple count
+ is required, the caller's <literal>DestReceiver</literal> object must
+ calculate it.
</para>
</refsect1>
</refentry>
<!-- *********************************************** -->
-<refentry id="spi-spi-execute-plan-with-receiver">
- <indexterm><primary>SPI_execute_plan_with_receiver</primary></indexterm>
+<refentry id="spi-spi-execute-plan-with-paramlist">
+ <indexterm><primary>SPI_execute_plan_with_paramlist</primary></indexterm>
<refmeta>
- <refentrytitle>SPI_execute_plan_with_receiver</refentrytitle>
+ <refentrytitle>SPI_execute_plan_with_paramlist</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
- <refname>SPI_execute_plan_with_receiver</refname>
+ <refname>SPI_execute_plan_with_paramlist</refname>
<refpurpose>execute a statement prepared by <function>SPI_prepare</function></refpurpose>
</refnamediv>
<refsynopsisdiv>
<synopsis>
-int SPI_execute_plan_with_receiver(SPIPlanPtr <parameter>plan</parameter>,
- ParamListInfo <parameter>params</parameter>,
- bool <parameter>read_only</parameter>,
- long <parameter>count</parameter>,
- DestReceiver *<parameter>dest</parameter>)
+int SPI_execute_plan_with_paramlist(SPIPlanPtr <parameter>plan</parameter>,
+ ParamListInfo <parameter>params</parameter>,
+ bool <parameter>read_only</parameter>,
+ long <parameter>count</parameter>)
</synopsis>
</refsynopsisdiv>
@@ -1844,15 +1914,19 @@ int SPI_execute_plan_with_receiver(SPIPlanPtr <parameter>plan</parameter>,
<title>Description</title>
<para>
- <function>SPI_execute_plan_with_receiver</function> executes a statement
- prepared by <function>SPI_prepare</function>. This function is
- equivalent to <function>SPI_execute_plan_with_paramlist</function>
- except that, instead of always accumulating the result tuples into a
- <varname>SPI_tuptable</varname> structure, tuples can be passed to a
- caller-supplied <literal>DestReceiver</literal> object as they are
- generated by the executor. This is particularly helpful for queries
- that might generate many tuples, since the data can be processed
- on-the-fly instead of being accumulated in memory.
+ <function>SPI_execute_plan_with_paramlist</function> executes a statement
+ prepared by <function>SPI_prepare</function>.
+ This function is equivalent to <function>SPI_execute_plan</function>
+ except that information about the parameter values to be passed to the
+ query is presented differently. The <literal>ParamListInfo</literal>
+ representation can be convenient for passing down values that are
+ already available in that format. It also supports use of dynamic
+ parameter sets via hook functions specified in <literal>ParamListInfo</literal>.
+ </para>
+
+ <para>
+ This function is now deprecated in favor
+ of <function>SPI_execute_plan_extended</function>.
</para>
</refsect1>
@@ -1894,17 +1968,6 @@ int SPI_execute_plan_with_receiver(SPIPlanPtr <parameter>plan</parameter>,
</para>
</listitem>
</varlistentry>
-
- <varlistentry>
- <term><literal>DestReceiver * <parameter>dest</parameter></literal></term>
- <listitem>
- <para>
- <literal>DestReceiver</literal> object that will receive any tuples
- emitted by the query; if NULL, this function is exactly equivalent to
- <function>SPI_execute_plan_with_paramlist</function>
- </para>
- </listitem>
- </varlistentry>
</variablelist>
</refsect1>
@@ -1916,15 +1979,9 @@ int SPI_execute_plan_with_receiver(SPIPlanPtr <parameter>plan</parameter>,
</para>
<para>
- When <parameter>dest</parameter> is NULL,
<varname>SPI_processed</varname> and
<varname>SPI_tuptable</varname> are set as in
- <function>SPI_execute_plan</function>.
- When <parameter>dest</parameter> is not NULL,
- <varname>SPI_processed</varname> is set to zero and
- <varname>SPI_tuptable</varname> is set to NULL. If a tuple count
- is required, the caller's <literal>DestReceiver</literal> object must
- calculate it.
+ <function>SPI_execute_plan</function> if successful.
</para>
</refsect1>
</refentry>