aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeIndexonlyscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeIndexonlyscan.c')
-rw-r--r--src/backend/executor/nodeIndexonlyscan.c96
1 files changed, 94 insertions, 2 deletions
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index e6635233155..f464cca9507 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -92,6 +92,7 @@ IndexOnlyNext(IndexOnlyScanState *node)
scandesc = index_beginscan(node->ss.ss_currentRelation,
node->ioss_RelationDesc,
estate->es_snapshot,
+ &node->ioss_Instrument,
node->ioss_NumScanKeys,
node->ioss_NumOrderByKeys);
@@ -414,6 +415,27 @@ ExecEndIndexOnlyScan(IndexOnlyScanState *node)
}
/*
+ * When ending a parallel worker, copy the statistics gathered by the
+ * worker back into shared memory so that it can be picked up by the main
+ * process to report in EXPLAIN ANALYZE
+ */
+ if (node->ioss_SharedInfo != NULL && IsParallelWorker())
+ {
+ IndexScanInstrumentation *winstrument;
+
+ Assert(ParallelWorkerNumber <= node->ioss_SharedInfo->num_workers);
+ winstrument = &node->ioss_SharedInfo->winstrument[ParallelWorkerNumber];
+
+ /*
+ * We have to accumulate the stats rather than performing a memcpy.
+ * When a Gather/GatherMerge node finishes it will perform planner
+ * shutdown on the workers. On rescan it will spin up new workers
+ * which will have a new IndexOnlyScanState and zeroed stats.
+ */
+ winstrument->nsearches += node->ioss_Instrument.nsearches;
+ }
+
+ /*
* close the index relation (no-op if we didn't open it)
*/
if (indexScanDesc)
@@ -707,11 +729,21 @@ 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);
+ estate->es_snapshot,
+ instrument, parallel_aware,
+ pcxt->nworkers);
shm_toc_estimate_chunk(&pcxt->estimator, node->ioss_PscanLen);
shm_toc_estimate_keys(&pcxt->estimator, 1);
}
@@ -728,16 +760,33 @@ 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,
- piscan);
+ instrument, parallel_aware, pcxt->nworkers,
+ &node->ioss_SharedInfo, 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,
+ &node->ioss_Instrument,
node->ioss_NumScanKeys,
node->ioss_NumOrderByKeys,
piscan);
@@ -764,6 +813,7 @@ void
ExecIndexOnlyScanReInitializeDSM(IndexOnlyScanState *node,
ParallelContext *pcxt)
{
+ Assert(node->ss.ps.plan->parallel_aware);
index_parallelrescan(node->ioss_ScanDesc);
}
@@ -778,11 +828,31 @@ 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,
+ &node->ioss_Instrument,
node->ioss_NumScanKeys,
node->ioss_NumOrderByKeys,
piscan);
@@ -797,3 +867,25 @@ ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node,
node->ioss_ScanKeys, node->ioss_NumScanKeys,
node->ioss_OrderByKeys, node->ioss_NumOrderByKeys);
}
+
+/* ----------------------------------------------------------------
+ * ExecIndexOnlyScanRetrieveInstrumentation
+ *
+ * Transfer index-only scan statistics from DSM to private memory.
+ * ----------------------------------------------------------------
+ */
+void
+ExecIndexOnlyScanRetrieveInstrumentation(IndexOnlyScanState *node)
+{
+ SharedIndexScanInstrumentation *SharedInfo = node->ioss_SharedInfo;
+ size_t size;
+
+ if (SharedInfo == NULL)
+ return;
+
+ /* Create a copy of SharedInfo in backend-local memory */
+ size = offsetof(SharedIndexScanInstrumentation, winstrument) +
+ SharedInfo->num_workers * sizeof(IndexScanInstrumentation);
+ node->ioss_SharedInfo = palloc(size);
+ memcpy(node->ioss_SharedInfo, SharedInfo, size);
+}