1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-25 20:23:07 +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:
Robert Haas
2017-02-19 15:53:59 +05:30
parent 16be2fd100
commit 0414b26bac
7 changed files with 191 additions and 26 deletions

View File

@@ -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);
}