diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index baa69fc..79eaf79 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -1394,6 +1394,9 @@ _bt_steppage(IndexScanDesc scan, ScanDirection dir) blkno = _bt_parallel_seize(scan, &status); if (status == false) { + /* release the previous buffer, if pinned */ + BTScanPosUnpinIfPinned(so->currPos); + BTScanPosInvalidate(so->currPos); return false; } diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index c55b7c4..08329b0 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -198,6 +198,11 @@ ExecParallelEstimate(PlanState *planstate, ExecParallelEstimateContext *e) ExecIndexScanEstimate((IndexScanState *) planstate, e->pcxt); break; + case T_IndexOnlyScanState: + ExecIndexOnlyScanEstimate((IndexOnlyScanState *) planstate, + e->pcxt); + break; + case T_ForeignScanState: ExecForeignScanEstimate((ForeignScanState *) planstate, e->pcxt); @@ -254,6 +259,11 @@ ExecParallelInitializeDSM(PlanState *planstate, ExecIndexScanInitializeDSM((IndexScanState *) planstate, d->pcxt); break; + case T_IndexOnlyScanState: + ExecIndexOnlyScanInitializeDSM((IndexOnlyScanState *) planstate, + d->pcxt); + break; + case T_ForeignScanState: ExecForeignScanInitializeDSM((ForeignScanState *) planstate, d->pcxt); @@ -701,6 +711,10 @@ ExecParallelInitializeWorker(PlanState *planstate, shm_toc *toc) case T_IndexScanState: ExecIndexScanInitializeWorker((IndexScanState *) planstate, toc); break; + case T_IndexOnlyScanState: + ExecIndexOnlyScanInitializeWorker((IndexOnlyScanState *) planstate, toc); + break; + case T_ForeignScanState: ExecForeignScanInitializeWorker((ForeignScanState *) planstate, toc); diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c index 45566bd..78304d1 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -21,6 +21,9 @@ * ExecEndIndexOnlyScan releases all storage. * ExecIndexOnlyMarkPos marks scan position. * ExecIndexOnlyRestrPos restores scan position. + * ExecIndexOnlyScanEstimate estimates DSM space needed for parallel index-only scan + * ExecIndexOnlyScanInitializeDSM initialize DSM for parallel index-only scan + * ExecIndexOnlyScanInitializeWorker attach to DSM info in parallel worker */ #include "postgres.h" @@ -277,6 +280,16 @@ ExecIndexOnlyScan(IndexOnlyScanState *node) void ExecReScanIndexOnlyScan(IndexOnlyScanState *node) { + bool reset_parallel_scan = true; + + /* + * if we are here to just update the scan keys, then don't reset parallel + * scan + */ + if (node->ioss_NumRuntimeKeys != 0 && !node->ioss_RuntimeKeysReady) + reset_parallel_scan = false; + + /* * If we are doing runtime key calculations (ie, any of the index key * values weren't simple Consts), compute the new key values. But first, @@ -296,10 +309,16 @@ ExecReScanIndexOnlyScan(IndexOnlyScanState *node) node->ioss_RuntimeKeysReady = true; /* reset index scan */ - index_rescan(node->ioss_ScanDesc, - node->ioss_ScanKeys, node->ioss_NumScanKeys, - node->ioss_OrderByKeys, node->ioss_NumOrderByKeys); + if (node->ioss_ScanDesc) + { + + index_rescan(node->ioss_ScanDesc, + node->ioss_ScanKeys, node->ioss_NumScanKeys, + node->ioss_OrderByKeys, node->ioss_NumOrderByKeys); + if (reset_parallel_scan) + index_parallelrescan(node->ioss_ScanDesc); + } ExecScanReScan(&node->ss); } @@ -534,33 +553,99 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) { indexstate->ioss_RuntimeContext = NULL; } - - /* - * Initialize scan descriptor. - */ - indexstate->ioss_ScanDesc = index_beginscan(currentRelation, + if (!node->scan.plan.parallel_aware) + { + /* + * Initialize scan descriptor. + */ + indexstate->ioss_ScanDesc = index_beginscan(currentRelation, indexstate->ioss_RelationDesc, estate->es_snapshot, NULL, indexstate->ioss_NumScanKeys, indexstate->ioss_NumOrderByKeys, false); - /* Set it up for index-only scan */ - indexstate->ioss_ScanDesc->xs_want_itup = true; - indexstate->ioss_VMBuffer = InvalidBuffer; + /* Set it up for index-only scan */ + indexstate->ioss_ScanDesc->xs_want_itup = true; + indexstate->ioss_VMBuffer = InvalidBuffer; - /* - * If no run-time keys to calculate, go ahead and pass the scankeys to the - * index AM. - */ - if (indexstate->ioss_NumRuntimeKeys == 0) - index_rescan(indexstate->ioss_ScanDesc, + /* + * If no run-time keys to calculate, go ahead and pass the scankeys to the + * index AM. + */ + if (indexstate->ioss_NumRuntimeKeys == 0) + index_rescan(indexstate->ioss_ScanDesc, indexstate->ioss_ScanKeys, indexstate->ioss_NumScanKeys, indexstate->ioss_OrderByKeys, indexstate->ioss_NumOrderByKeys); - + } /* * all done. */ return indexstate; } +void +ExecIndexOnlyScanEstimate(IndexOnlyScanState *node, + ParallelContext *pcxt) +{ + EState *estate = node->ss.ps.state; + + node->ioss_PscanLen = index_parallelscan_estimate(node->ioss_RelationDesc, + estate->es_snapshot); + shm_toc_estimate_chunk(&pcxt->estimator, node->ioss_PscanLen); + shm_toc_estimate_keys(&pcxt->estimator, 1); +} + +void +ExecIndexOnlyScanInitializeDSM(IndexOnlyScanState *node, + ParallelContext *pcxt) +{ + EState *estate = node->ss.ps.state; + ParallelIndexScanDesc piscan; + + piscan = shm_toc_allocate(pcxt->toc, node->ioss_PscanLen); + index_parallelscan_initialize(node->ss.ss_currentRelation, + node->ioss_RelationDesc, + estate->es_snapshot, + piscan); + shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, piscan); + node->ioss_ScanDesc = + index_beginscan_parallel(node->ss.ss_currentRelation, + node->ioss_RelationDesc, + node->ioss_NumScanKeys, + node->ioss_NumOrderByKeys, + piscan); + node->ioss_ScanDesc->xs_want_itup = true; + + /* + * If no run-time keys to calculate, go ahead and pass the scankeys to the + * index AM. + */ + if (node->ioss_NumRuntimeKeys == 0) + index_rescan(node->ioss_ScanDesc, + node->ioss_ScanKeys, node->ioss_NumScanKeys, + node->ioss_OrderByKeys, node->ioss_NumOrderByKeys); +} +void +ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node, shm_toc *toc) +{ + ParallelIndexScanDesc piscan; + + piscan = shm_toc_lookup(toc, node->ss.ps.plan->plan_node_id); + node->ioss_ScanDesc = + index_beginscan_parallel(node->ss.ss_currentRelation, + node->ioss_RelationDesc, + node->ioss_NumScanKeys, + node->ioss_NumOrderByKeys, + piscan); + node->ioss_ScanDesc->xs_want_itup = true; + + /* + * If no run-time keys to calculate, go ahead and pass the scankeys to the + * index AM. + */ + if (node->ioss_NumRuntimeKeys == 0) + index_rescan(node->ioss_ScanDesc, + node->ioss_ScanKeys, node->ioss_NumScanKeys, + node->ioss_OrderByKeys, node->ioss_NumOrderByKeys); +} diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 54a8a2f..5d963f5 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -1098,8 +1098,8 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel, * If appropriate, consider parallel index scan. We don't allow * parallel index scan for bitmap scans. */ - if (index->amcanparallel && - !index_only_scan && + if ((index->amcanparallel || + index_only_scan) && rel->consider_parallel && outer_relids == NULL && scantype != ST_BITMAPSCAN) diff --git a/src/include/executor/nodeIndexonlyscan.h b/src/include/executor/nodeIndexonlyscan.h index d63d194..143d8cd 100644 --- a/src/include/executor/nodeIndexonlyscan.h +++ b/src/include/executor/nodeIndexonlyscan.h @@ -14,6 +14,7 @@ #ifndef NODEINDEXONLYSCAN_H #define NODEINDEXONLYSCAN_H +#include "access/parallel.h" #include "nodes/execnodes.h" extern IndexOnlyScanState *ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags); @@ -23,4 +24,8 @@ extern void ExecIndexOnlyMarkPos(IndexOnlyScanState *node); extern void ExecIndexOnlyRestrPos(IndexOnlyScanState *node); extern void ExecReScanIndexOnlyScan(IndexOnlyScanState *node); +extern void ExecIndexOnlyScanEstimate(IndexOnlyScanState *node, ParallelContext *pcxt); +extern void ExecIndexOnlyScanInitializeDSM(IndexOnlyScanState *node, ParallelContext *pcxt); +extern void ExecIndexOnlyScanInitializeWorker(IndexOnlyScanState *node, shm_toc *toc); + #endif /* NODEINDEXONLYSCAN_H */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 17d712a..b8f22da 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1397,6 +1397,8 @@ typedef struct IndexOnlyScanState IndexScanDesc ioss_ScanDesc; Buffer ioss_VMBuffer; long ioss_HeapFetches; + /* This is needed for parallel index scan */ + Size ioss_PscanLen; } IndexOnlyScanState; /* ----------------