mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
Add optimizer and executor support for parallel index-only scans.
Commit 5262f7a4fc
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
This commit is contained in:
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user