diff options
author | Robert Haas <rhaas@postgresql.org> | 2017-02-19 15:53:59 +0530 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2017-02-19 15:57:55 +0530 |
commit | 0414b26bac09379a4cbf1fbd847d1cee2293c5e4 (patch) | |
tree | 16554f77178d068e27bd53c2404a6f8468c90746 /src/backend/executor | |
parent | 16be2fd100199bdf284becfcee02c5eb20d8a11d (diff) | |
download | postgresql-0414b26bac09379a4cbf1fbd847d1cee2293c5e4.tar.gz postgresql-0414b26bac09379a4cbf1fbd847d1cee2293c5e4.zip |
Add optimizer and executor support for parallel index-only scans.
Commit 5262f7a4fc44f651241d2ff1fa688dd664a34874 added similar support
for parallel index scans; this extends that work to index-only scans.
As with parallel index scans, this requires support from the index AM,
so currently parallel index-only scans will only be possible for btree
indexes.
Rafia Sabih, reviewed and tested by Rahila Syed, Tushar Ahuja,
and Amit Kapila
Discussion: http://postgr.es/m/CAOGQiiPEAs4C=TBp0XShxBvnWXuzGL2u++Hm1=qnCpd6_Mf8Fw@mail.gmail.com
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execParallel.c | 12 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexonlyscan.c | 154 |
2 files changed, 147 insertions, 19 deletions
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index 98d4f1eca76..646df087f9f 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -29,6 +29,7 @@ #include "executor/nodeForeignscan.h" #include "executor/nodeSeqscan.h" #include "executor/nodeIndexscan.h" +#include "executor/nodeIndexonlyscan.h" #include "executor/tqueue.h" #include "nodes/nodeFuncs.h" #include "optimizer/planmain.h" @@ -202,6 +203,10 @@ 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); @@ -258,6 +263,10 @@ 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); @@ -737,6 +746,9 @@ 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 d5b19b7c115..66c2ad66d71 100644 --- a/src/backend/executor/nodeIndexonlyscan.c +++ b/src/backend/executor/nodeIndexonlyscan.c @@ -21,6 +21,11 @@ * 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 +282,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. For detailed reason behind this look in the comments for + * ExecReScanIndexScan. + */ + 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 +311,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 && node->ioss_ScanDesc->parallel_scan) + index_parallelrescan(node->ioss_ScanDesc); + } ExecScanReScan(&node->ss); } @@ -536,29 +557,124 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) /* * Initialize scan descriptor. */ - indexstate->ioss_ScanDesc = index_beginscan(currentRelation, - indexstate->ioss_RelationDesc, - estate->es_snapshot, + if (!node->scan.plan.parallel_aware) + { + indexstate->ioss_ScanDesc = index_beginscan(currentRelation, + indexstate->ioss_RelationDesc, + estate->es_snapshot, indexstate->ioss_NumScanKeys, indexstate->ioss_NumOrderByKeys); - /* 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, - indexstate->ioss_ScanKeys, - indexstate->ioss_NumScanKeys, - indexstate->ioss_OrderByKeys, - indexstate->ioss_NumOrderByKeys); + /* 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, + indexstate->ioss_ScanKeys, + indexstate->ioss_NumScanKeys, + indexstate->ioss_OrderByKeys, + indexstate->ioss_NumOrderByKeys); + } /* * all done. */ return indexstate; } + +/* ---------------------------------------------------------------- + * Parallel Index-only Scan Support + * ---------------------------------------------------------------- + */ + +/* ---------------------------------------------------------------- + * ExecIndexOnlyScanEstimate + * + * estimates the space required to serialize index-only scan node. + * ---------------------------------------------------------------- + */ +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); +} + +/* ---------------------------------------------------------------- + * ExecIndexOnlyScanInitializeDSM + * + * Set up a parallel index-only scan descriptor. + * ---------------------------------------------------------------- + */ +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; + node->ioss_VMBuffer = InvalidBuffer; + + /* + * 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); +} + +/* ---------------------------------------------------------------- + * ExecIndexOnlyScanInitializeWorker + * + * Copy relevant information from TOC into planstate. + * ---------------------------------------------------------------- + */ +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); +} |