mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
Make sequential scans parallel-aware.
In addition, this path fills in a number of missing bits and pieces in the parallel infrastructure. Paths and plans now have a parallel_aware flag indicating whether whatever parallel-aware logic they have should be engaged. It is believed that we will need this flag for a number of path/plan types, not just sequential scans, which is why the flag is generic rather than part of the SeqScan structures specifically. Also, execParallel.c now gives parallel nodes a chance to initialize their PlanState nodes from the DSM during parallel worker startup. Amit Kapila, with a fair amount of adjustment by me. Review of previous patch versions by Haribabu Kommi and others.
This commit is contained in:
@ -19,6 +19,10 @@
|
||||
* ExecInitSeqScan creates and initializes a seqscan node.
|
||||
* ExecEndSeqScan releases any storage allocated.
|
||||
* ExecReScanSeqScan rescans the relation
|
||||
*
|
||||
* ExecSeqScanEstimate estimates DSM space needed for parallel scan
|
||||
* ExecSeqScanInitializeDSM initialize DSM for parallel scan
|
||||
* ExecSeqScanInitializeWorker attach to DSM info in parallel worker
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
@ -53,10 +57,22 @@ SeqNext(SeqScanState *node)
|
||||
/*
|
||||
* get information from the estate and scan state
|
||||
*/
|
||||
scandesc = node->ss_currentScanDesc;
|
||||
estate = node->ps.state;
|
||||
scandesc = node->ss.ss_currentScanDesc;
|
||||
estate = node->ss.ps.state;
|
||||
direction = estate->es_direction;
|
||||
slot = node->ss_ScanTupleSlot;
|
||||
slot = node->ss.ss_ScanTupleSlot;
|
||||
|
||||
if (scandesc == NULL)
|
||||
{
|
||||
/*
|
||||
* We reach here if the scan is not parallel, or if we're executing
|
||||
* a scan that was intended to be parallel serially.
|
||||
*/
|
||||
scandesc = heap_beginscan(node->ss.ss_currentRelation,
|
||||
estate->es_snapshot,
|
||||
0, NULL);
|
||||
node->ss.ss_currentScanDesc = scandesc;
|
||||
}
|
||||
|
||||
/*
|
||||
* get the next tuple from the table
|
||||
@ -123,27 +139,19 @@ static void
|
||||
InitScanRelation(SeqScanState *node, EState *estate, int eflags)
|
||||
{
|
||||
Relation currentRelation;
|
||||
HeapScanDesc currentScanDesc;
|
||||
|
||||
/*
|
||||
* get the relation object id from the relid'th entry in the range table,
|
||||
* open that relation and acquire appropriate lock on it.
|
||||
*/
|
||||
currentRelation = ExecOpenScanRelation(estate,
|
||||
((SeqScan *) node->ps.plan)->scanrelid,
|
||||
((SeqScan *) node->ss.ps.plan)->scanrelid,
|
||||
eflags);
|
||||
|
||||
/* initialize a heapscan */
|
||||
currentScanDesc = heap_beginscan(currentRelation,
|
||||
estate->es_snapshot,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
node->ss_currentRelation = currentRelation;
|
||||
node->ss_currentScanDesc = currentScanDesc;
|
||||
node->ss.ss_currentRelation = currentRelation;
|
||||
|
||||
/* and report the scan tuple slot's rowtype */
|
||||
ExecAssignScanType(node, RelationGetDescr(currentRelation));
|
||||
ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation));
|
||||
}
|
||||
|
||||
|
||||
@ -167,44 +175,44 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
|
||||
* create state structure
|
||||
*/
|
||||
scanstate = makeNode(SeqScanState);
|
||||
scanstate->ps.plan = (Plan *) node;
|
||||
scanstate->ps.state = estate;
|
||||
scanstate->ss.ps.plan = (Plan *) node;
|
||||
scanstate->ss.ps.state = estate;
|
||||
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* create expression context for node
|
||||
*/
|
||||
ExecAssignExprContext(estate, &scanstate->ps);
|
||||
ExecAssignExprContext(estate, &scanstate->ss.ps);
|
||||
|
||||
/*
|
||||
* initialize child expressions
|
||||
*/
|
||||
scanstate->ps.targetlist = (List *)
|
||||
scanstate->ss.ps.targetlist = (List *)
|
||||
ExecInitExpr((Expr *) node->plan.targetlist,
|
||||
(PlanState *) scanstate);
|
||||
scanstate->ps.qual = (List *)
|
||||
scanstate->ss.ps.qual = (List *)
|
||||
ExecInitExpr((Expr *) node->plan.qual,
|
||||
(PlanState *) scanstate);
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &scanstate->ps);
|
||||
ExecInitScanTupleSlot(estate, scanstate);
|
||||
ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
|
||||
ExecInitScanTupleSlot(estate, &scanstate->ss);
|
||||
|
||||
/*
|
||||
* initialize scan relation
|
||||
*/
|
||||
InitScanRelation(scanstate, estate, eflags);
|
||||
|
||||
scanstate->ps.ps_TupFromTlist = false;
|
||||
scanstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* Initialize result tuple type and projection info.
|
||||
*/
|
||||
ExecAssignResultTypeFromTL(&scanstate->ps);
|
||||
ExecAssignScanProjectionInfo(scanstate);
|
||||
ExecAssignResultTypeFromTL(&scanstate->ss.ps);
|
||||
ExecAssignScanProjectionInfo(&scanstate->ss);
|
||||
|
||||
return scanstate;
|
||||
}
|
||||
@ -224,24 +232,25 @@ ExecEndSeqScan(SeqScanState *node)
|
||||
/*
|
||||
* get information from node
|
||||
*/
|
||||
relation = node->ss_currentRelation;
|
||||
scanDesc = node->ss_currentScanDesc;
|
||||
relation = node->ss.ss_currentRelation;
|
||||
scanDesc = node->ss.ss_currentScanDesc;
|
||||
|
||||
/*
|
||||
* Free the exprcontext
|
||||
*/
|
||||
ExecFreeExprContext(&node->ps);
|
||||
ExecFreeExprContext(&node->ss.ps);
|
||||
|
||||
/*
|
||||
* clean out the tuple table
|
||||
*/
|
||||
ExecClearTuple(node->ps.ps_ResultTupleSlot);
|
||||
ExecClearTuple(node->ss_ScanTupleSlot);
|
||||
ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
|
||||
ExecClearTuple(node->ss.ss_ScanTupleSlot);
|
||||
|
||||
/*
|
||||
* close heap scan
|
||||
*/
|
||||
heap_endscan(scanDesc);
|
||||
if (scanDesc != NULL)
|
||||
heap_endscan(scanDesc);
|
||||
|
||||
/*
|
||||
* close the heap relation.
|
||||
@ -265,10 +274,71 @@ ExecReScanSeqScan(SeqScanState *node)
|
||||
{
|
||||
HeapScanDesc scan;
|
||||
|
||||
scan = node->ss_currentScanDesc;
|
||||
scan = node->ss.ss_currentScanDesc;
|
||||
|
||||
heap_rescan(scan, /* scan desc */
|
||||
NULL); /* new scan keys */
|
||||
if (scan != NULL)
|
||||
heap_rescan(scan, /* scan desc */
|
||||
NULL); /* new scan keys */
|
||||
|
||||
ExecScanReScan((ScanState *) node);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* Parallel Scan Support
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecSeqScanEstimate
|
||||
*
|
||||
* estimates the space required to serialize seqscan node.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecSeqScanEstimate(SeqScanState *node,
|
||||
ParallelContext *pcxt)
|
||||
{
|
||||
EState *estate = node->ss.ps.state;
|
||||
|
||||
node->pscan_len = heap_parallelscan_estimate(estate->es_snapshot);
|
||||
shm_toc_estimate_chunk(&pcxt->estimator, node->pscan_len);
|
||||
shm_toc_estimate_keys(&pcxt->estimator, 1);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecSeqScanInitializeDSM
|
||||
*
|
||||
* Set up a parallel heap scan descriptor.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecSeqScanInitializeDSM(SeqScanState *node,
|
||||
ParallelContext *pcxt)
|
||||
{
|
||||
EState *estate = node->ss.ps.state;
|
||||
ParallelHeapScanDesc pscan;
|
||||
|
||||
pscan = shm_toc_allocate(pcxt->toc, node->pscan_len);
|
||||
heap_parallelscan_initialize(pscan,
|
||||
node->ss.ss_currentRelation,
|
||||
estate->es_snapshot);
|
||||
shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pscan);
|
||||
node->ss.ss_currentScanDesc =
|
||||
heap_beginscan_parallel(node->ss.ss_currentRelation, pscan);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecSeqScanInitializeWorker
|
||||
*
|
||||
* Copy relevant information from TOC into planstate.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecSeqScanInitializeWorker(SeqScanState *node, shm_toc *toc)
|
||||
{
|
||||
ParallelHeapScanDesc pscan;
|
||||
|
||||
pscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id);
|
||||
node->ss.ss_currentScanDesc =
|
||||
heap_beginscan_parallel(node->ss.ss_currentRelation, pscan);
|
||||
}
|
||||
|
Reference in New Issue
Block a user