1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

Parallel executor support.

This code provides infrastructure for a parallel leader to start up
parallel workers to execute subtrees of the plan tree being executed
in the master.  User-supplied parameters from ParamListInfo are passed
down, but PARAM_EXEC parameters are not.  Various other constructs,
such as initplans, subplans, and CTEs, are also not currently shared.
Nevertheless, there's enough here to support a basic implementation of
parallel query, and we can lift some of the current restrictions as
needed.

Amit Kapila and Robert Haas
This commit is contained in:
Robert Haas
2015-09-28 21:55:57 -04:00
parent 0557dc276f
commit d1b7c1ffe7
17 changed files with 1007 additions and 2 deletions

View File

@ -112,6 +112,7 @@ CopyPlanFields(const Plan *from, Plan *newnode)
COPY_SCALAR_FIELD(total_cost);
COPY_SCALAR_FIELD(plan_rows);
COPY_SCALAR_FIELD(plan_width);
COPY_SCALAR_FIELD(plan_node_id);
COPY_NODE_FIELD(targetlist);
COPY_NODE_FIELD(qual);
COPY_NODE_FIELD(lefttree);

View File

@ -271,6 +271,7 @@ _outPlanInfo(StringInfo str, const Plan *node)
WRITE_FLOAT_FIELD(total_cost, "%.2f");
WRITE_FLOAT_FIELD(plan_rows, "%.0f");
WRITE_INT_FIELD(plan_width);
WRITE_INT_FIELD(plan_node_id);
WRITE_NODE_FIELD(targetlist);
WRITE_NODE_FIELD(qual);
WRITE_NODE_FIELD(lefttree);

View File

@ -16,6 +16,7 @@
#include "postgres.h"
#include "nodes/params.h"
#include "storage/shmem.h"
#include "utils/datum.h"
#include "utils/lsyscache.h"
@ -73,3 +74,157 @@ copyParamList(ParamListInfo from)
return retval;
}
/*
* Estimate the amount of space required to serialize a ParamListInfo.
*/
Size
EstimateParamListSpace(ParamListInfo paramLI)
{
int i;
Size sz = sizeof(int);
if (paramLI == NULL || paramLI->numParams <= 0)
return sz;
for (i = 0; i < paramLI->numParams; i++)
{
ParamExternData *prm = &paramLI->params[i];
int16 typLen;
bool typByVal;
/* give hook a chance in case parameter is dynamic */
if (!OidIsValid(prm->ptype) && paramLI->paramFetch != NULL)
(*paramLI->paramFetch) (paramLI, i + 1);
sz = add_size(sz, sizeof(Oid)); /* space for type OID */
sz = add_size(sz, sizeof(uint16)); /* space for pflags */
/* space for datum/isnull */
if (OidIsValid(prm->ptype))
get_typlenbyval(prm->ptype, &typLen, &typByVal);
else
{
/* If no type OID, assume by-value, like copyParamList does. */
typLen = sizeof(Datum);
typByVal = true;
}
sz = add_size(sz,
datumEstimateSpace(prm->value, prm->isnull, typByVal, typLen));
}
return sz;
}
/*
* Serialize a paramListInfo structure into caller-provided storage.
*
* We write the number of parameters first, as a 4-byte integer, and then
* write details for each parameter in turn. The details for each parameter
* consist of a 4-byte type OID, 2 bytes of flags, and then the datum as
* serialized by datumSerialize(). The caller is responsible for ensuring
* that there is enough storage to store the number of bytes that will be
* written; use EstimateParamListSpace to find out how many will be needed.
* *start_address is updated to point to the byte immediately following those
* written.
*
* RestoreParamList can be used to recreate a ParamListInfo based on the
* serialized representation; this will be a static, self-contained copy
* just as copyParamList would create.
*/
void
SerializeParamList(ParamListInfo paramLI, char **start_address)
{
int nparams;
int i;
/* Write number of parameters. */
if (paramLI == NULL || paramLI->numParams <= 0)
nparams = 0;
else
nparams = paramLI->numParams;
memcpy(*start_address, &nparams, sizeof(int));
*start_address += sizeof(int);
/* Write each parameter in turn. */
for (i = 0; i < nparams; i++)
{
ParamExternData *prm = &paramLI->params[i];
int16 typLen;
bool typByVal;
/* give hook a chance in case parameter is dynamic */
if (!OidIsValid(prm->ptype) && paramLI->paramFetch != NULL)
(*paramLI->paramFetch) (paramLI, i + 1);
/* Write type OID. */
memcpy(*start_address, &prm->ptype, sizeof(Oid));
*start_address += sizeof(Oid);
/* Write flags. */
memcpy(*start_address, &prm->pflags, sizeof(uint16));
*start_address += sizeof(uint16);
/* Write datum/isnull. */
if (OidIsValid(prm->ptype))
get_typlenbyval(prm->ptype, &typLen, &typByVal);
else
{
/* If no type OID, assume by-value, like copyParamList does. */
typLen = sizeof(Datum);
typByVal = true;
}
datumSerialize(prm->value, prm->isnull, typByVal, typLen,
start_address);
}
}
/*
* Copy a ParamListInfo structure.
*
* The result is allocated in CurrentMemoryContext.
*
* Note: the intent of this function is to make a static, self-contained
* set of parameter values. If dynamic parameter hooks are present, we
* intentionally do not copy them into the result. Rather, we forcibly
* instantiate all available parameter values and copy the datum values.
*/
ParamListInfo
RestoreParamList(char **start_address)
{
ParamListInfo paramLI;
Size size;
int i;
int nparams;
memcpy(&nparams, *start_address, sizeof(int));
*start_address += sizeof(int);
size = offsetof(ParamListInfoData, params) +
nparams * sizeof(ParamExternData);
paramLI = (ParamListInfo) palloc(size);
paramLI->paramFetch = NULL;
paramLI->paramFetchArg = NULL;
paramLI->parserSetup = NULL;
paramLI->parserSetupArg = NULL;
paramLI->numParams = nparams;
for (i = 0; i < nparams; i++)
{
ParamExternData *prm = &paramLI->params[i];
/* Read type OID. */
memcpy(&prm->ptype, *start_address, sizeof(Oid));
*start_address += sizeof(Oid);
/* Read flags. */
memcpy(&prm->pflags, *start_address, sizeof(uint16));
*start_address += sizeof(uint16);
/* Read datum/isnull. */
prm->value = datumRestore(start_address, &prm->isnull);
}
return paramLI;
}

View File

@ -1413,6 +1413,7 @@ ReadCommonPlan(Plan *local_node)
READ_FLOAT_FIELD(total_cost);
READ_FLOAT_FIELD(plan_rows);
READ_INT_FIELD(plan_width);
READ_INT_FIELD(plan_node_id);
READ_NODE_FIELD(targetlist);
READ_NODE_FIELD(qual);
READ_NODE_FIELD(lefttree);