diff options
Diffstat (limited to 'src/backend/executor/nodeIndexonlyscan.c')
-rw-r--r-- | src/backend/executor/nodeIndexonlyscan.c | 96 |
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); +} |