On Mon, Apr 6, 2026 at 10:01 AM Melanie Plageman
<[email protected]> wrote:
>
> On Mon, Apr 6, 2026 at 5:15 AM Tomas Vondra <[email protected]> wrote:
> >
> > Anyway, that doesn't matter much, because the more I look at the
> > approach with having a separate chunk of shared memory, the more I like
> > it. It seems much simpler, more elegant, etc. I really disliked how
> > unreadable the code got with the parallel_aware/instrument checks in
> > multiple places, and this just gets rid of that. I like that.
> >
> <--snip-->
> >
> > Is execParallel.h the right place to define the offset? It means the
> > various nodes (like nodeBitmapHeapScan) now have to include this header,
> > and it seems a bit suspicious. I can't think of a better .h file, and
> > maybe I'm wrong and it's perfectly fine.
>
> It could go in src/include/executor is instrument_node.h. It's where
> the structs for the shared instrumentation go. It's probably cheaper
> to include also because it doesn't include anything.
I cleaned up the first patch in the set that refactors index-only and
index scan to use this pattern and realized that I wasn't sure what to
do about the duplication between index-only and index scans for these
functions.
ExecIndexScanInstrumentEstimate() and
ExecIndexOnlyScanInstrumentEstimate() are the same code except they
take different node types to do the check for intsrumentation
if (!node->ss.ps.instrument || pcxt->nworkers == 0)
return;
The size estimation for SharedIndexScanIntrumentation could be common
to the two but it is only three lines and doesn't seem worth another
function call. ExecIndex[Only]ScanEstimate() use a common helper
index_parallelscan_estimate() but that is more code.
We could just have a common helper and only call it if
node->ss.ps.instrument && pcxt->nworkers > 0 but I don't see anybody
else in ExecParallelEstimate() checking for instrumentation being
enabled.
Besides that, the function names are very long already but don't
include the word parallel (though ExecIndexScanEstimate() is for
parallel scans only and doesn't include "parallel").
ExecIndex[Only]ScanInstrumentInitDSM() is the same between the two
except the node type it takes but three different members of node are
used here, so I'm not sure how much sense a common helper makes here.
I have a feeling the above stuff isn't okay how it is now, but I'm not
sure which direction to go.
I think ExecIndex[Only]ScanInstrumentInitWorker() is fine the way it
is because it is only 1 line and requires a different node for
index/index-only.
- Melanie
From f68de64b8747c9fe1e71fbcbd2285b7f1fc3a41a Mon Sep 17 00:00:00 2001
From: Melanie Plageman <[email protected]>
Date: Mon, 6 Apr 2026 12:26:15 -0400
Subject: [PATCH v9] Allocate separate DSM chunk for parallel Index[Only]Scan
instrumentation
Parallel index and index-only scans may or may not be parallel-aware and
may or may not be instrumented (for EXPLAIN ANALYZE). Non-parallel-aware
scans still need shared instrumentation to report per-worker statistics
to the leader. Because all combinations of parallel-aware and
instrumented are possible, it is cleaner to allocate separate DSM chunks
for the shared instrumentation and the parallel scan descriptor. This is
of particular interest now because a future commit will extend this
pattern to other scan node types.
---
src/backend/access/index/indexam.c | 51 ++--------
src/backend/executor/execParallel.c | 40 ++++++--
src/backend/executor/nodeBitmapIndexscan.c | 9 +-
src/backend/executor/nodeIndexonlyscan.c | 108 ++++++++++++--------
src/backend/executor/nodeIndexscan.c | 113 +++++++++++++--------
src/include/access/genam.h | 7 +-
src/include/access/relscan.h | 1 -
src/include/executor/instrument_node.h | 11 ++
src/include/executor/nodeIndexonlyscan.h | 6 ++
src/include/executor/nodeIndexscan.h | 6 ++
10 files changed, 198 insertions(+), 154 deletions(-)
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 23288a4f994..7967e939847 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -463,43 +463,26 @@ index_restrpos(IndexScanDesc scan)
}
/*
- * index_parallelscan_estimate - estimate shared memory for parallel scan
- *
- * When instrument=true, estimate includes SharedIndexScanInstrumentation
- * space. When parallel_aware=true, estimate includes whatever space the
- * index AM's amestimateparallelscan routine requested when called.
+ * Estimates the shared memory needed for parallel scan, including any
+ * AM-specific parallel scan state.
*/
Size
index_parallelscan_estimate(Relation indexRelation, int nkeys, int norderbys,
- Snapshot snapshot, bool instrument,
- bool parallel_aware, int nworkers)
+ Snapshot snapshot)
{
Size nbytes;
- Assert(instrument || parallel_aware);
-
RELATION_CHECKS;
nbytes = offsetof(ParallelIndexScanDescData, ps_snapshot_data);
nbytes = add_size(nbytes, EstimateSnapshotSpace(snapshot));
nbytes = MAXALIGN(nbytes);
- if (instrument)
- {
- Size sharedinfosz;
-
- sharedinfosz = offsetof(SharedIndexScanInstrumentation, winstrument) +
- nworkers * sizeof(IndexScanInstrumentation);
- nbytes = add_size(nbytes, sharedinfosz);
- nbytes = MAXALIGN(nbytes);
- }
-
/*
* If parallel scan index AM interface can't be used (or index AM provides
* no such interface), assume there is no AM-specific data needed
*/
- if (parallel_aware &&
- indexRelation->rd_indam->amestimateparallelscan != NULL)
+ if (indexRelation->rd_indam->amestimateparallelscan != NULL)
nbytes = add_size(nbytes,
indexRelation->rd_indam->amestimateparallelscan(indexRelation,
nkeys,
@@ -520,15 +503,11 @@ index_parallelscan_estimate(Relation indexRelation, int nkeys, int norderbys,
*/
void
index_parallelscan_initialize(Relation heapRelation, Relation indexRelation,
- Snapshot snapshot, bool instrument,
- bool parallel_aware, int nworkers,
- SharedIndexScanInstrumentation **sharedinfo,
+ Snapshot snapshot,
ParallelIndexScanDesc target)
{
Size offset;
- Assert(instrument || parallel_aware);
-
RELATION_CHECKS;
offset = add_size(offsetof(ParallelIndexScanDescData, ps_snapshot_data),
@@ -537,29 +516,11 @@ index_parallelscan_initialize(Relation heapRelation, Relation indexRelation,
target->ps_locator = heapRelation->rd_locator;
target->ps_indexlocator = indexRelation->rd_locator;
- target->ps_offset_ins = 0;
target->ps_offset_am = 0;
SerializeSnapshot(snapshot, target->ps_snapshot_data);
- if (instrument)
- {
- Size sharedinfosz;
-
- target->ps_offset_ins = offset;
- sharedinfosz = offsetof(SharedIndexScanInstrumentation, winstrument) +
- nworkers * sizeof(IndexScanInstrumentation);
- offset = add_size(offset, sharedinfosz);
- offset = MAXALIGN(offset);
-
- /* Set leader's *sharedinfo pointer, and initialize stats */
- *sharedinfo = (SharedIndexScanInstrumentation *)
- OffsetToPointer(target, target->ps_offset_ins);
- memset(*sharedinfo, 0, sharedinfosz);
- (*sharedinfo)->num_workers = nworkers;
- }
-
/* aminitparallelscan is optional; assume no-op if not provided by AM */
- if (parallel_aware && indexRelation->rd_indam->aminitparallelscan != NULL)
+ if (indexRelation->rd_indam->aminitparallelscan != NULL)
{
void *amtarget;
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index 5e4a4a9740c..726aca230a4 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -259,14 +259,20 @@ ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e)
e->pcxt);
break;
case T_IndexScanState:
+ if (planstate->plan->parallel_aware)
+ ExecIndexScanEstimate((IndexScanState *) planstate,
+ e->pcxt);
/* even when not parallel-aware, for EXPLAIN ANALYZE */
- ExecIndexScanEstimate((IndexScanState *) planstate,
- e->pcxt);
+ ExecIndexScanInstrumentEstimate((IndexScanState *) planstate,
+ e->pcxt);
break;
case T_IndexOnlyScanState:
+ if (planstate->plan->parallel_aware)
+ ExecIndexOnlyScanEstimate((IndexOnlyScanState *) planstate,
+ e->pcxt);
/* even when not parallel-aware, for EXPLAIN ANALYZE */
- ExecIndexOnlyScanEstimate((IndexOnlyScanState *) planstate,
- e->pcxt);
+ ExecIndexOnlyScanInstrumentEstimate((IndexOnlyScanState *) planstate,
+ e->pcxt);
break;
case T_BitmapIndexScanState:
/* even when not parallel-aware, for EXPLAIN ANALYZE */
@@ -493,13 +499,20 @@ ExecParallelInitializeDSM(PlanState *planstate,
d->pcxt);
break;
case T_IndexScanState:
+ if (planstate->plan->parallel_aware)
+ ExecIndexScanInitializeDSM((IndexScanState *) planstate,
+ d->pcxt);
/* even when not parallel-aware, for EXPLAIN ANALYZE */
- ExecIndexScanInitializeDSM((IndexScanState *) planstate, d->pcxt);
+ ExecIndexScanInstrumentInitDSM((IndexScanState *) planstate,
+ d->pcxt);
break;
case T_IndexOnlyScanState:
+ if (planstate->plan->parallel_aware)
+ ExecIndexOnlyScanInitializeDSM((IndexOnlyScanState *) planstate,
+ d->pcxt);
/* even when not parallel-aware, for EXPLAIN ANALYZE */
- ExecIndexOnlyScanInitializeDSM((IndexOnlyScanState *) planstate,
- d->pcxt);
+ ExecIndexOnlyScanInstrumentInitDSM((IndexOnlyScanState *) planstate,
+ d->pcxt);
break;
case T_BitmapIndexScanState:
/* even when not parallel-aware, for EXPLAIN ANALYZE */
@@ -1371,13 +1384,20 @@ ExecParallelInitializeWorker(PlanState *planstate, ParallelWorkerContext *pwcxt)
ExecSeqScanInitializeWorker((SeqScanState *) planstate, pwcxt);
break;
case T_IndexScanState:
+ if (planstate->plan->parallel_aware)
+ ExecIndexScanInitializeWorker((IndexScanState *) planstate,
+ pwcxt);
/* even when not parallel-aware, for EXPLAIN ANALYZE */
- ExecIndexScanInitializeWorker((IndexScanState *) planstate, pwcxt);
+ ExecIndexScanInstrumentInitWorker((IndexScanState *) planstate,
+ pwcxt);
break;
case T_IndexOnlyScanState:
+ if (planstate->plan->parallel_aware)
+ ExecIndexOnlyScanInitializeWorker((IndexOnlyScanState *) planstate,
+ pwcxt);
/* even when not parallel-aware, for EXPLAIN ANALYZE */
- ExecIndexOnlyScanInitializeWorker((IndexOnlyScanState *) planstate,
- pwcxt);
+ ExecIndexOnlyScanInstrumentInitWorker((IndexOnlyScanState *) planstate,
+ pwcxt);
break;
case T_BitmapIndexScanState:
/* even when not parallel-aware, for EXPLAIN ANALYZE */
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c
index 70c55ee6d61..7978514e1bc 100644
--- a/src/backend/executor/nodeBitmapIndexscan.c
+++ b/src/backend/executor/nodeBitmapIndexscan.c
@@ -394,7 +394,9 @@ ExecBitmapIndexScanInitializeDSM(BitmapIndexScanState *node,
node->biss_SharedInfo =
(SharedIndexScanInstrumentation *) shm_toc_allocate(pcxt->toc,
size);
- shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id,
+ shm_toc_insert(pcxt->toc,
+ node->ss.ps.plan->plan_node_id +
+ PARALLEL_KEY_SCAN_INSTRUMENT_OFFSET,
node->biss_SharedInfo);
/* Each per-worker area must start out as zeroes */
@@ -417,7 +419,10 @@ ExecBitmapIndexScanInitializeWorker(BitmapIndexScanState *node,
return;
node->biss_SharedInfo = (SharedIndexScanInstrumentation *)
- shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
+ shm_toc_lookup(pwcxt->toc,
+ node->ss.ps.plan->plan_node_id +
+ PARALLEL_KEY_SCAN_INSTRUMENT_OFFSET,
+ false);
}
/* ----------------------------------------------------------------
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index de6154fd541..3e4cc0b9402 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -736,21 +736,11 @@ ExecIndexOnlyScanEstimate(IndexOnlyScanState *node,
ParallelContext *pcxt)
{
EState *estate = node->ss.ps.state;
- bool instrument = (node->ss.ps.instrument != NULL);
- bool parallel_aware = node->ss.ps.plan->parallel_aware;
-
- if (!instrument && !parallel_aware)
- {
- /* No DSM required by the scan */
- return;
- }
node->ioss_PscanLen = index_parallelscan_estimate(node->ioss_RelationDesc,
node->ioss_NumScanKeys,
node->ioss_NumOrderByKeys,
- estate->es_snapshot,
- instrument, parallel_aware,
- pcxt->nworkers);
+ estate->es_snapshot);
shm_toc_estimate_chunk(&pcxt->estimator, node->ioss_PscanLen);
shm_toc_estimate_keys(&pcxt->estimator, 1);
}
@@ -767,29 +757,14 @@ ExecIndexOnlyScanInitializeDSM(IndexOnlyScanState *node,
{
EState *estate = node->ss.ps.state;
ParallelIndexScanDesc piscan;
- bool instrument = node->ss.ps.instrument != NULL;
- bool parallel_aware = node->ss.ps.plan->parallel_aware;
-
- if (!instrument && !parallel_aware)
- {
- /* No DSM required by the scan */
- return;
- }
piscan = shm_toc_allocate(pcxt->toc, node->ioss_PscanLen);
index_parallelscan_initialize(node->ss.ss_currentRelation,
node->ioss_RelationDesc,
estate->es_snapshot,
- instrument, parallel_aware, pcxt->nworkers,
- &node->ioss_SharedInfo, piscan);
+ piscan);
shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan);
- if (!parallel_aware)
- {
- /* Only here to initialize SharedInfo in DSM */
- return;
- }
-
node->ioss_ScanDesc =
index_beginscan_parallel(node->ss.ss_currentRelation,
node->ioss_RelationDesc,
@@ -837,27 +812,9 @@ ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node,
ParallelWorkerContext *pwcxt)
{
ParallelIndexScanDesc piscan;
- bool instrument = node->ss.ps.instrument != NULL;
- bool parallel_aware = node->ss.ps.plan->parallel_aware;
-
- if (!instrument && !parallel_aware)
- {
- /* No DSM required by the scan */
- return;
- }
piscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
- if (instrument)
- node->ioss_SharedInfo = (SharedIndexScanInstrumentation *)
- OffsetToPointer(piscan, piscan->ps_offset_ins);
-
- if (!parallel_aware)
- {
- /* Only here to set up worker node's SharedInfo */
- return;
- }
-
node->ioss_ScanDesc =
index_beginscan_parallel(node->ss.ss_currentRelation,
node->ioss_RelationDesc,
@@ -879,6 +836,67 @@ ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node,
node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
}
+/*
+ * Compute the amount of DSM we'll need for the shared instrumentation and
+ * inform pcxt->estimator.
+ */
+void
+ExecIndexOnlyScanInstrumentEstimate(IndexOnlyScanState *node,
+ ParallelContext *pcxt)
+{
+ Size size;
+
+ /* don't need this if not instrumenting or no workers */
+ if (!node->ss.ps.instrument || pcxt->nworkers == 0)
+ return;
+
+ size = offsetof(SharedIndexScanInstrumentation, winstrument) +
+ pcxt->nworkers * sizeof(IndexScanInstrumentation);
+ shm_toc_estimate_chunk(&pcxt->estimator, size);
+ shm_toc_estimate_keys(&pcxt->estimator, 1);
+}
+
+/*
+ * Set up parallel index-only scan instrumentation.
+ */
+void
+ExecIndexOnlyScanInstrumentInitDSM(IndexOnlyScanState *node,
+ ParallelContext *pcxt)
+{
+ Size size;
+
+ /* don't need this if not instrumenting or no workers */
+ if (!node->ss.ps.instrument || pcxt->nworkers == 0)
+ return;
+
+ size = offsetof(SharedIndexScanInstrumentation, winstrument) +
+ pcxt->nworkers * sizeof(IndexScanInstrumentation);
+ node->ioss_SharedInfo =
+ (SharedIndexScanInstrumentation *) shm_toc_allocate(pcxt->toc, size);
+
+ /* Each per-worker area must start out as zeroes */
+ memset(node->ioss_SharedInfo, 0, size);
+ node->ioss_SharedInfo->num_workers = pcxt->nworkers;
+ shm_toc_insert(pcxt->toc,
+ node->ss.ps.plan->plan_node_id +
+ PARALLEL_KEY_SCAN_INSTRUMENT_OFFSET,
+ node->ioss_SharedInfo);
+}
+
+/*
+ * Look up and save the location of the shared instrumentation.
+ */
+void
+ExecIndexOnlyScanInstrumentInitWorker(IndexOnlyScanState *node,
+ ParallelWorkerContext *pwcxt)
+{
+ node->ioss_SharedInfo = (SharedIndexScanInstrumentation *)
+ shm_toc_lookup(pwcxt->toc,
+ node->ss.ps.plan->plan_node_id +
+ PARALLEL_KEY_SCAN_INSTRUMENT_OFFSET,
+ true);
+}
+
/* ----------------------------------------------------------------
* ExecIndexOnlyScanRetrieveInstrumentation
*
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 1620d146071..095ce538f04 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -1674,21 +1674,11 @@ ExecIndexScanEstimate(IndexScanState *node,
ParallelContext *pcxt)
{
EState *estate = node->ss.ps.state;
- bool instrument = node->ss.ps.instrument != NULL;
- bool parallel_aware = node->ss.ps.plan->parallel_aware;
-
- if (!instrument && !parallel_aware)
- {
- /* No DSM required by the scan */
- return;
- }
node->iss_PscanLen = index_parallelscan_estimate(node->iss_RelationDesc,
node->iss_NumScanKeys,
node->iss_NumOrderByKeys,
- estate->es_snapshot,
- instrument, parallel_aware,
- pcxt->nworkers);
+ estate->es_snapshot);
shm_toc_estimate_chunk(&pcxt->estimator, node->iss_PscanLen);
shm_toc_estimate_keys(&pcxt->estimator, 1);
}
@@ -1705,29 +1695,14 @@ ExecIndexScanInitializeDSM(IndexScanState *node,
{
EState *estate = node->ss.ps.state;
ParallelIndexScanDesc piscan;
- bool instrument = node->ss.ps.instrument != NULL;
- bool parallel_aware = node->ss.ps.plan->parallel_aware;
-
- if (!instrument && !parallel_aware)
- {
- /* No DSM required by the scan */
- return;
- }
piscan = shm_toc_allocate(pcxt->toc, node->iss_PscanLen);
index_parallelscan_initialize(node->ss.ss_currentRelation,
node->iss_RelationDesc,
estate->es_snapshot,
- instrument, parallel_aware, pcxt->nworkers,
- &node->iss_SharedInfo, piscan);
+ piscan);
shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan);
- if (!parallel_aware)
- {
- /* Only here to initialize SharedInfo in DSM */
- return;
- }
-
node->iss_ScanDesc =
index_beginscan_parallel(node->ss.ss_currentRelation,
node->iss_RelationDesc,
@@ -1773,27 +1748,9 @@ ExecIndexScanInitializeWorker(IndexScanState *node,
ParallelWorkerContext *pwcxt)
{
ParallelIndexScanDesc piscan;
- bool instrument = node->ss.ps.instrument != NULL;
- bool parallel_aware = node->ss.ps.plan->parallel_aware;
-
- if (!instrument && !parallel_aware)
- {
- /* No DSM required by the scan */
- return;
- }
piscan = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
- if (instrument)
- node->iss_SharedInfo = (SharedIndexScanInstrumentation *)
- OffsetToPointer(piscan, piscan->ps_offset_ins);
-
- if (!parallel_aware)
- {
- /* Only here to set up worker node's SharedInfo */
- return;
- }
-
node->iss_ScanDesc =
index_beginscan_parallel(node->ss.ss_currentRelation,
node->iss_RelationDesc,
@@ -1814,6 +1771,72 @@ ExecIndexScanInitializeWorker(IndexScanState *node,
node->iss_OrderByKeys, node->iss_NumOrderByKeys);
}
+/*
+ * Compute the amount of DSM we'll need for the shared instrumentation and
+ * inform pcxt->estimator.
+ */
+void
+ExecIndexScanInstrumentEstimate(IndexScanState *node,
+ ParallelContext *pcxt)
+{
+ Size size;
+
+ /* don't need this if not instrumenting or no workers */
+ if (!node->ss.ps.instrument || pcxt->nworkers == 0)
+ return;
+
+ /*
+ * This size calculation is trivial enough that we don't bother saving it
+ * in the IndexScanState. We'll recalculate the needed size in
+ * ExecIndexScanInstrumentInitDSM().
+ */
+ size = offsetof(SharedIndexScanInstrumentation, winstrument) +
+ pcxt->nworkers * sizeof(IndexScanInstrumentation);
+ shm_toc_estimate_chunk(&pcxt->estimator, size);
+ shm_toc_estimate_keys(&pcxt->estimator, 1);
+}
+
+/*
+ * Set up parallel index scan instrumentation.
+ */
+void
+ExecIndexScanInstrumentInitDSM(IndexScanState *node,
+ ParallelContext *pcxt)
+{
+ Size size;
+
+ /* don't need this if not instrumenting or no workers */
+ if (!node->ss.ps.instrument || pcxt->nworkers == 0)
+ return;
+
+ size = offsetof(SharedIndexScanInstrumentation, winstrument) +
+ pcxt->nworkers * sizeof(IndexScanInstrumentation);
+ node->iss_SharedInfo =
+ (SharedIndexScanInstrumentation *) shm_toc_allocate(pcxt->toc, size);
+
+ /* Each per-worker area must start out as zeroes */
+ memset(node->iss_SharedInfo, 0, size);
+ node->iss_SharedInfo->num_workers = pcxt->nworkers;
+ shm_toc_insert(pcxt->toc,
+ node->ss.ps.plan->plan_node_id +
+ PARALLEL_KEY_SCAN_INSTRUMENT_OFFSET,
+ node->iss_SharedInfo);
+}
+
+/*
+ * Look up and save the location of the shared instrumentation.
+ */
+void
+ExecIndexScanInstrumentInitWorker(IndexScanState *node,
+ ParallelWorkerContext *pwcxt)
+{
+ node->iss_SharedInfo = (SharedIndexScanInstrumentation *)
+ shm_toc_lookup(pwcxt->toc,
+ node->ss.ps.plan->plan_node_id +
+ PARALLEL_KEY_SCAN_INSTRUMENT_OFFSET,
+ true);
+}
+
/* ----------------------------------------------------------------
* ExecIndexScanRetrieveInstrumentation
*
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index b69320a7fc8..68bfe405db3 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -171,14 +171,9 @@ extern void index_endscan(IndexScanDesc scan);
extern void index_markpos(IndexScanDesc scan);
extern void index_restrpos(IndexScanDesc scan);
extern Size index_parallelscan_estimate(Relation indexRelation,
- int nkeys, int norderbys, Snapshot snapshot,
- bool instrument, bool parallel_aware,
- int nworkers);
+ int nkeys, int norderbys, Snapshot snapshot);
extern void index_parallelscan_initialize(Relation heapRelation,
Relation indexRelation, Snapshot snapshot,
- bool instrument, bool parallel_aware,
- int nworkers,
- SharedIndexScanInstrumentation **sharedinfo,
ParallelIndexScanDesc target);
extern void index_parallelrescan(IndexScanDesc scan);
extern IndexScanDesc index_beginscan_parallel(Relation heaprel,
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 960abf6c214..fd2076c582a 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -203,7 +203,6 @@ typedef struct ParallelIndexScanDescData
{
RelFileLocator ps_locator; /* physical table relation to scan */
RelFileLocator ps_indexlocator; /* physical index relation to scan */
- Size ps_offset_ins; /* Offset to SharedIndexScanInstrumentation */
Size ps_offset_am; /* Offset to am-specific structure */
char ps_snapshot_data[FLEXIBLE_ARRAY_MEMBER];
} ParallelIndexScanDescData;
diff --git a/src/include/executor/instrument_node.h b/src/include/executor/instrument_node.h
index 2a0ff377a73..46db2dd70c4 100644
--- a/src/include/executor/instrument_node.h
+++ b/src/include/executor/instrument_node.h
@@ -18,6 +18,17 @@
#ifndef INSTRUMENT_NODE_H
#define INSTRUMENT_NODE_H
+/*
+ * Offset added to plan_node_id to create a second TOC key for per-worker scan
+ * instrumentation. This allows scan nodes to store instrumentation in a
+ * separate DSM allocation from their parallel scan descriptor. This is useful
+ * because scans may be non-parallel-aware but still require instrumentation or
+ * parallel-aware and not require instrumentation. Having two allocations
+ * provides flexibility to allocate and initialize what is needed. In the
+ * future, if nodes need more than two DSM allocations, we would need a more
+ * robust system.
+ */
+#define PARALLEL_KEY_SCAN_INSTRUMENT_OFFSET UINT64CONST(0xD000000000000000)
/* ---------------------
* Instrumentation information for aggregate function execution
diff --git a/src/include/executor/nodeIndexonlyscan.h b/src/include/executor/nodeIndexonlyscan.h
index ba807b8d8d9..b686244eb91 100644
--- a/src/include/executor/nodeIndexonlyscan.h
+++ b/src/include/executor/nodeIndexonlyscan.h
@@ -32,6 +32,12 @@ extern void ExecIndexOnlyScanReInitializeDSM(IndexOnlyScanState *node,
ParallelContext *pcxt);
extern void ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node,
ParallelWorkerContext *pwcxt);
+extern void ExecIndexOnlyScanInstrumentEstimate(IndexOnlyScanState *node,
+ ParallelContext *pcxt);
+extern void ExecIndexOnlyScanInstrumentInitDSM(IndexOnlyScanState *node,
+ ParallelContext *pcxt);
+extern void ExecIndexOnlyScanInstrumentInitWorker(IndexOnlyScanState *node,
+ ParallelWorkerContext *pwcxt);
extern void ExecIndexOnlyScanRetrieveInstrumentation(IndexOnlyScanState *node);
#endif /* NODEINDEXONLYSCAN_H */
diff --git a/src/include/executor/nodeIndexscan.h b/src/include/executor/nodeIndexscan.h
index 803be5b08df..c60cbc9a94b 100644
--- a/src/include/executor/nodeIndexscan.h
+++ b/src/include/executor/nodeIndexscan.h
@@ -28,6 +28,12 @@ extern void ExecIndexScanInitializeDSM(IndexScanState *node, ParallelContext *pc
extern void ExecIndexScanReInitializeDSM(IndexScanState *node, ParallelContext *pcxt);
extern void ExecIndexScanInitializeWorker(IndexScanState *node,
ParallelWorkerContext *pwcxt);
+extern void ExecIndexScanInstrumentEstimate(IndexScanState *node,
+ ParallelContext *pcxt);
+extern void ExecIndexScanInstrumentInitDSM(IndexScanState *node,
+ ParallelContext *pcxt);
+extern void ExecIndexScanInstrumentInitWorker(IndexScanState *node,
+ ParallelWorkerContext *pwcxt);
extern void ExecIndexScanRetrieveInstrumentation(IndexScanState *node);
/*
--
2.43.0