PostgreSQL Source Code  git master
nodeBitmapHeapscan.c File Reference
#include "postgres.h"
#include <math.h>
#include "access/relscan.h"
#include "access/transam.h"
#include "access/visibilitymap.h"
#include "executor/execdebug.h"
#include "executor/nodeBitmapHeapscan.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/bufmgr.h"
#include "storage/predicate.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/spccache.h"
#include "utils/snapmgr.h"
#include "utils/tqual.h"
Include dependency graph for nodeBitmapHeapscan.c:

Go to the source code of this file.

Functions

static TupleTableSlotBitmapHeapNext (BitmapHeapScanState *node)
 
static void bitgetpage (HeapScanDesc scan, TBMIterateResult *tbmres)
 
static void BitmapDoneInitializingSharedState (ParallelBitmapHeapState *pstate)
 
static void BitmapAdjustPrefetchIterator (BitmapHeapScanState *node, TBMIterateResult *tbmres)
 
static void BitmapAdjustPrefetchTarget (BitmapHeapScanState *node)
 
static void BitmapPrefetch (BitmapHeapScanState *node, HeapScanDesc scan)
 
static bool BitmapShouldInitializeSharedState (ParallelBitmapHeapState *pstate)
 
static bool BitmapHeapRecheck (BitmapHeapScanState *node, TupleTableSlot *slot)
 
static TupleTableSlotExecBitmapHeapScan (PlanState *pstate)
 
void ExecReScanBitmapHeapScan (BitmapHeapScanState *node)
 
void ExecEndBitmapHeapScan (BitmapHeapScanState *node)
 
BitmapHeapScanStateExecInitBitmapHeapScan (BitmapHeapScan *node, EState *estate, int eflags)
 
void ExecBitmapHeapEstimate (BitmapHeapScanState *node, ParallelContext *pcxt)
 
void ExecBitmapHeapInitializeDSM (BitmapHeapScanState *node, ParallelContext *pcxt)
 
void ExecBitmapHeapReInitializeDSM (BitmapHeapScanState *node, ParallelContext *pcxt)
 
void ExecBitmapHeapInitializeWorker (BitmapHeapScanState *node, ParallelWorkerContext *pwcxt)
 

Function Documentation

◆ bitgetpage()

static void bitgetpage ( HeapScanDesc  scan,
TBMIterateResult tbmres 
)
static

Definition at line 383 of file nodeBitmapHeapscan.c.

References Assert, TBMIterateResult::blockno, buffer, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage, CheckForSerializableConflictOut(), FirstOffsetNumber, heap_hot_search_buffer(), heap_page_prune_opt(), HeapTupleSatisfiesVisibility, ItemIdGetLength, ItemIdIsNormal, ItemPointerGetOffsetNumber, ItemPointerSet, LockBuffer(), MaxHeapTuplesPerPage, TBMIterateResult::ntuples, OffsetNumberNext, TBMIterateResult::offsets, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PredicateLockTuple(), RelationData::rd_id, ReleaseAndReadBuffer(), HeapScanDescData::rs_cbuf, HeapScanDescData::rs_ntuples, HeapScanDescData::rs_rd, HeapScanDescData::rs_snapshot, HeapScanDescData::rs_vistuples, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, and HeapTupleData::t_tableOid.

Referenced by BitmapHeapNext().

384 {
385  BlockNumber page = tbmres->blockno;
386  Buffer buffer;
387  Snapshot snapshot;
388  int ntup;
389 
390  /*
391  * Acquire pin on the target heap page, trading in any pin we held before.
392  */
393  Assert(page < scan->rs_nblocks);
394 
395  scan->rs_cbuf = ReleaseAndReadBuffer(scan->rs_cbuf,
396  scan->rs_rd,
397  page);
398  buffer = scan->rs_cbuf;
399  snapshot = scan->rs_snapshot;
400 
401  ntup = 0;
402 
403  /*
404  * Prune and repair fragmentation for the whole page, if possible.
405  */
406  heap_page_prune_opt(scan->rs_rd, buffer);
407 
408  /*
409  * We must hold share lock on the buffer content while examining tuple
410  * visibility. Afterwards, however, the tuples we have found to be
411  * visible are guaranteed good as long as we hold the buffer pin.
412  */
413  LockBuffer(buffer, BUFFER_LOCK_SHARE);
414 
415  /*
416  * We need two separate strategies for lossy and non-lossy cases.
417  */
418  if (tbmres->ntuples >= 0)
419  {
420  /*
421  * Bitmap is non-lossy, so we just look through the offsets listed in
422  * tbmres; but we have to follow any HOT chain starting at each such
423  * offset.
424  */
425  int curslot;
426 
427  for (curslot = 0; curslot < tbmres->ntuples; curslot++)
428  {
429  OffsetNumber offnum = tbmres->offsets[curslot];
430  ItemPointerData tid;
431  HeapTupleData heapTuple;
432 
433  ItemPointerSet(&tid, page, offnum);
434  if (heap_hot_search_buffer(&tid, scan->rs_rd, buffer, snapshot,
435  &heapTuple, NULL, true))
436  scan->rs_vistuples[ntup++] = ItemPointerGetOffsetNumber(&tid);
437  }
438  }
439  else
440  {
441  /*
442  * Bitmap is lossy, so we must examine each item pointer on the page.
443  * But we can ignore HOT chains, since we'll check each tuple anyway.
444  */
445  Page dp = (Page) BufferGetPage(buffer);
447  OffsetNumber offnum;
448 
449  for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum))
450  {
451  ItemId lp;
452  HeapTupleData loctup;
453  bool valid;
454 
455  lp = PageGetItemId(dp, offnum);
456  if (!ItemIdIsNormal(lp))
457  continue;
458  loctup.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
459  loctup.t_len = ItemIdGetLength(lp);
460  loctup.t_tableOid = scan->rs_rd->rd_id;
461  ItemPointerSet(&loctup.t_self, page, offnum);
462  valid = HeapTupleSatisfiesVisibility(&loctup, snapshot, buffer);
463  if (valid)
464  {
465  scan->rs_vistuples[ntup++] = offnum;
466  PredicateLockTuple(scan->rs_rd, &loctup, snapshot);
467  }
468  CheckForSerializableConflictOut(valid, scan->rs_rd, &loctup,
469  buffer, snapshot);
470  }
471  }
472 
474 
475  Assert(ntup <= MaxHeapTuplesPerPage);
476  scan->rs_ntuples = ntup;
477 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define MaxHeapTuplesPerPage
Definition: htup_details.h:587
uint32 BlockNumber
Definition: block.h:31
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
void CheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
Definition: predicate.c:3899
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)
Definition: tqual.h:45
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:68
BlockNumber blockno
Definition: tidbitmap.h:42
bool heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer, Snapshot snapshot, HeapTuple heapTuple, bool *all_dead, bool first_call)
Definition: heapam.c:2038
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]
Definition: tidbitmap.h:46
#define FirstOffsetNumber
Definition: off.h:27
Snapshot rs_snapshot
Definition: relscan.h:50
Oid t_tableOid
Definition: htup.h:66
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
Oid rd_id
Definition: rel.h:86
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
Relation rs_rd
Definition: relscan.h:49
Buffer rs_cbuf
Definition: relscan.h:72
#define Assert(condition)
Definition: c.h:699
OffsetNumber rs_vistuples[MaxHeapTuplesPerPage]
Definition: relscan.h:79
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation, BlockNumber blockNum)
Definition: bufmgr.c:1513
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:117
void PredicateLockTuple(Relation relation, HeapTuple tuple, Snapshot snapshot)
Definition: predicate.c:2497
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
void heap_page_prune_opt(Relation relation, Buffer buffer)
Definition: pruneheap.c:74
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:127

◆ BitmapAdjustPrefetchIterator()

static void BitmapAdjustPrefetchIterator ( BitmapHeapScanState node,
TBMIterateResult tbmres 
)
inlinestatic

Definition at line 498 of file nodeBitmapHeapscan.c.

References TBMIterateResult::blockno, elog, ERROR, ParallelBitmapHeapState::mutex, BitmapHeapScanState::prefetch_iterator, BitmapHeapScanState::prefetch_maximum, ParallelBitmapHeapState::prefetch_pages, BitmapHeapScanState::prefetch_pages, BitmapHeapScanState::pstate, BitmapHeapScanState::shared_prefetch_iterator, SpinLockAcquire, SpinLockRelease, tbm_iterate(), and tbm_shared_iterate().

Referenced by BitmapHeapNext().

500 {
501 #ifdef USE_PREFETCH
502  ParallelBitmapHeapState *pstate = node->pstate;
503 
504  if (pstate == NULL)
505  {
506  TBMIterator *prefetch_iterator = node->prefetch_iterator;
507 
508  if (node->prefetch_pages > 0)
509  {
510  /* The main iterator has closed the distance by one page */
511  node->prefetch_pages--;
512  }
513  else if (prefetch_iterator)
514  {
515  /* Do not let the prefetch iterator get behind the main one */
516  TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
517 
518  if (tbmpre == NULL || tbmpre->blockno != tbmres->blockno)
519  elog(ERROR, "prefetch and main iterators are out of sync");
520  }
521  return;
522  }
523 
524  if (node->prefetch_maximum > 0)
525  {
526  TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
527 
528  SpinLockAcquire(&pstate->mutex);
529  if (pstate->prefetch_pages > 0)
530  {
531  pstate->prefetch_pages--;
532  SpinLockRelease(&pstate->mutex);
533  }
534  else
535  {
536  /* Release the mutex before iterating */
537  SpinLockRelease(&pstate->mutex);
538 
539  /*
540  * In case of shared mode, we can not ensure that the current
541  * blockno of the main iterator and that of the prefetch iterator
542  * are same. It's possible that whatever blockno we are
543  * prefetching will be processed by another process. Therefore,
544  * we don't validate the blockno here as we do in non-parallel
545  * case.
546  */
547  if (prefetch_iterator)
548  tbm_shared_iterate(prefetch_iterator);
549  }
550  }
551 #endif /* USE_PREFETCH */
552 }
BlockNumber blockno
Definition: tidbitmap.h:42
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:43
ParallelBitmapHeapState * pstate
Definition: execnodes.h:1459
#define SpinLockRelease(lock)
Definition: spin.h:64
TBMIterateResult * tbm_iterate(TBMIterator *iterator)
Definition: tidbitmap.c:970
TBMIterateResult * tbm_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1051
TBMIterator * prefetch_iterator
Definition: execnodes.h:1451
#define elog
Definition: elog.h:219
TBMSharedIterator * shared_prefetch_iterator
Definition: execnodes.h:1458

◆ BitmapAdjustPrefetchTarget()

static void BitmapAdjustPrefetchTarget ( BitmapHeapScanState node)
inlinestatic

Definition at line 563 of file nodeBitmapHeapscan.c.

References ParallelBitmapHeapState::mutex, BitmapHeapScanState::prefetch_maximum, ParallelBitmapHeapState::prefetch_target, BitmapHeapScanState::prefetch_target, BitmapHeapScanState::pstate, SpinLockAcquire, and SpinLockRelease.

Referenced by BitmapHeapNext().

564 {
565 #ifdef USE_PREFETCH
566  ParallelBitmapHeapState *pstate = node->pstate;
567 
568  if (pstate == NULL)
569  {
570  if (node->prefetch_target >= node->prefetch_maximum)
571  /* don't increase any further */ ;
572  else if (node->prefetch_target >= node->prefetch_maximum / 2)
573  node->prefetch_target = node->prefetch_maximum;
574  else if (node->prefetch_target > 0)
575  node->prefetch_target *= 2;
576  else
577  node->prefetch_target++;
578  return;
579  }
580 
581  /* Do an unlocked check first to save spinlock acquisitions. */
582  if (pstate->prefetch_target < node->prefetch_maximum)
583  {
584  SpinLockAcquire(&pstate->mutex);
585  if (pstate->prefetch_target >= node->prefetch_maximum)
586  /* don't increase any further */ ;
587  else if (pstate->prefetch_target >= node->prefetch_maximum / 2)
588  pstate->prefetch_target = node->prefetch_maximum;
589  else if (pstate->prefetch_target > 0)
590  pstate->prefetch_target *= 2;
591  else
592  pstate->prefetch_target++;
593  SpinLockRelease(&pstate->mutex);
594  }
595 #endif /* USE_PREFETCH */
596 }
#define SpinLockAcquire(lock)
Definition: spin.h:62
ParallelBitmapHeapState * pstate
Definition: execnodes.h:1459
#define SpinLockRelease(lock)
Definition: spin.h:64

◆ BitmapDoneInitializingSharedState()

static void BitmapDoneInitializingSharedState ( ParallelBitmapHeapState pstate)
inlinestatic

Definition at line 486 of file nodeBitmapHeapscan.c.

References BM_FINISHED, ConditionVariableBroadcast(), ParallelBitmapHeapState::cv, ParallelBitmapHeapState::mutex, SpinLockAcquire, SpinLockRelease, and ParallelBitmapHeapState::state.

Referenced by BitmapHeapNext().

487 {
488  SpinLockAcquire(&pstate->mutex);
489  pstate->state = BM_FINISHED;
490  SpinLockRelease(&pstate->mutex);
491  ConditionVariableBroadcast(&pstate->cv);
492 }
void ConditionVariableBroadcast(ConditionVariable *cv)
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define SpinLockRelease(lock)
Definition: spin.h:64
SharedBitmapState state
Definition: execnodes.h:1409
ConditionVariable cv
Definition: execnodes.h:1410

◆ BitmapHeapNext()

static TupleTableSlot * BitmapHeapNext ( BitmapHeapScanState node)
static

Definition at line 76 of file nodeBitmapHeapscan.c.

References Assert, bitgetpage(), BitmapAdjustPrefetchIterator(), BitmapAdjustPrefetchTarget(), BitmapDoneInitializingSharedState(), BitmapPrefetch(), BitmapHeapScanState::bitmapqualorig, BitmapShouldInitializeSharedState(), TBMIterateResult::blockno, BufferGetPage, BitmapHeapScanState::can_skip_fetch, CHECK_FOR_INTERRUPTS, ExprContext::ecxt_scantuple, elog, ERROR, EState::es_query_dsa, BitmapHeapScanState::exact_pages, ExecClearTuple(), ExecQualAndReset(), ExecStoreAllNullTuple(), ExecStoreTuple(), BitmapHeapScanState::initialized, InstrCountFiltered2, IsA, ItemIdGetLength, ItemIdIsNormal, ItemPointerSet, BitmapHeapScanState::lossy_pages, MultiExecProcNode(), ParallelBitmapHeapState::mutex, TBMIterateResult::ntuples, outerPlanState, PageGetItem, PageGetItemId, pgstat_count_heap_fetch, ParallelBitmapHeapState::prefetch_iterator, BitmapHeapScanState::prefetch_iterator, BitmapHeapScanState::prefetch_maximum, ParallelBitmapHeapState::prefetch_pages, BitmapHeapScanState::prefetch_pages, ParallelBitmapHeapState::prefetch_target, BitmapHeapScanState::prefetch_target, ScanState::ps, PlanState::ps_ExprContext, BitmapHeapScanState::pstate, RelationData::rd_id, TBMIterateResult::recheck, HeapScanDescData::rs_cbuf, HeapScanDescData::rs_cindex, HeapScanDescData::rs_ctup, HeapScanDescData::rs_nblocks, HeapScanDescData::rs_ntuples, HeapScanDescData::rs_rd, HeapScanDescData::rs_vistuples, BitmapHeapScanState::shared_prefetch_iterator, BitmapHeapScanState::shared_tbmiterator, BitmapHeapScanState::skip_fetch, SpinLockAcquire, SpinLockRelease, BitmapHeapScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, ScanState::ss_ScanTupleSlot, PlanState::state, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, BitmapHeapScanState::tbm, tbm_attach_shared_iterate(), tbm_begin_iterate(), tbm_iterate(), tbm_prepare_shared_iterate(), tbm_shared_iterate(), ParallelBitmapHeapState::tbmiterator, BitmapHeapScanState::tbmiterator, BitmapHeapScanState::tbmres, VM_ALL_VISIBLE, and BitmapHeapScanState::vmbuffer.

Referenced by ExecBitmapHeapScan().

77 {
78  ExprContext *econtext;
79  HeapScanDesc scan;
80  TIDBitmap *tbm;
81  TBMIterator *tbmiterator = NULL;
82  TBMSharedIterator *shared_tbmiterator = NULL;
83  TBMIterateResult *tbmres;
84  OffsetNumber targoffset;
85  TupleTableSlot *slot;
86  ParallelBitmapHeapState *pstate = node->pstate;
87  dsa_area *dsa = node->ss.ps.state->es_query_dsa;
88 
89  /*
90  * extract necessary information from index scan node
91  */
92  econtext = node->ss.ps.ps_ExprContext;
93  slot = node->ss.ss_ScanTupleSlot;
94  scan = node->ss.ss_currentScanDesc;
95  tbm = node->tbm;
96  if (pstate == NULL)
97  tbmiterator = node->tbmiterator;
98  else
99  shared_tbmiterator = node->shared_tbmiterator;
100  tbmres = node->tbmres;
101 
102  /*
103  * If we haven't yet performed the underlying index scan, do it, and begin
104  * the iteration over the bitmap.
105  *
106  * For prefetching, we use *two* iterators, one for the pages we are
107  * actually scanning and another that runs ahead of the first for
108  * prefetching. node->prefetch_pages tracks exactly how many pages ahead
109  * the prefetch iterator is. Also, node->prefetch_target tracks the
110  * desired prefetch distance, which starts small and increases up to the
111  * node->prefetch_maximum. This is to avoid doing a lot of prefetching in
112  * a scan that stops after a few tuples because of a LIMIT.
113  */
114  if (!node->initialized)
115  {
116  if (!pstate)
117  {
118  tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
119 
120  if (!tbm || !IsA(tbm, TIDBitmap))
121  elog(ERROR, "unrecognized result from subplan");
122 
123  node->tbm = tbm;
124  node->tbmiterator = tbmiterator = tbm_begin_iterate(tbm);
125  node->tbmres = tbmres = NULL;
126 
127 #ifdef USE_PREFETCH
128  if (node->prefetch_maximum > 0)
129  {
131  node->prefetch_pages = 0;
132  node->prefetch_target = -1;
133  }
134 #endif /* USE_PREFETCH */
135  }
136  else
137  {
138  /*
139  * The leader will immediately come out of the function, but
140  * others will be blocked until leader populates the TBM and wakes
141  * them up.
142  */
144  {
145  tbm = (TIDBitmap *) MultiExecProcNode(outerPlanState(node));
146  if (!tbm || !IsA(tbm, TIDBitmap))
147  elog(ERROR, "unrecognized result from subplan");
148 
149  node->tbm = tbm;
150 
151  /*
152  * Prepare to iterate over the TBM. This will return the
153  * dsa_pointer of the iterator state which will be used by
154  * multiple processes to iterate jointly.
155  */
157 #ifdef USE_PREFETCH
158  if (node->prefetch_maximum > 0)
159  {
160  pstate->prefetch_iterator =
162 
163  /*
164  * We don't need the mutex here as we haven't yet woke up
165  * others.
166  */
167  pstate->prefetch_pages = 0;
168  pstate->prefetch_target = -1;
169  }
170 #endif
171 
172  /* We have initialized the shared state so wake up others. */
174  }
175 
176  /* Allocate a private iterator and attach the shared state to it */
177  node->shared_tbmiterator = shared_tbmiterator =
179  node->tbmres = tbmres = NULL;
180 
181 #ifdef USE_PREFETCH
182  if (node->prefetch_maximum > 0)
183  {
186  }
187 #endif /* USE_PREFETCH */
188  }
189  node->initialized = true;
190  }
191 
192  for (;;)
193  {
194  Page dp;
195  ItemId lp;
196 
198 
199  /*
200  * Get next page of results if needed
201  */
202  if (tbmres == NULL)
203  {
204  if (!pstate)
205  node->tbmres = tbmres = tbm_iterate(tbmiterator);
206  else
207  node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
208  if (tbmres == NULL)
209  {
210  /* no more entries in the bitmap */
211  break;
212  }
213 
214  BitmapAdjustPrefetchIterator(node, tbmres);
215 
216  /*
217  * Ignore any claimed entries past what we think is the end of the
218  * relation. (This is probably not necessary given that we got at
219  * least AccessShareLock on the table before performing any of the
220  * indexscans, but let's be safe.)
221  */
222  if (tbmres->blockno >= scan->rs_nblocks)
223  {
224  node->tbmres = tbmres = NULL;
225  continue;
226  }
227 
228  /*
229  * We can skip fetching the heap page if we don't need any fields
230  * from the heap, and the bitmap entries don't need rechecking,
231  * and all tuples on the page are visible to our transaction.
232  */
233  node->skip_fetch = (node->can_skip_fetch &&
234  !tbmres->recheck &&
236  tbmres->blockno,
237  &node->vmbuffer));
238 
239  if (node->skip_fetch)
240  {
241  /*
242  * The number of tuples on this page is put into
243  * scan->rs_ntuples; note we don't fill scan->rs_vistuples.
244  */
245  scan->rs_ntuples = tbmres->ntuples;
246  }
247  else
248  {
249  /*
250  * Fetch the current heap page and identify candidate tuples.
251  */
252  bitgetpage(scan, tbmres);
253  }
254 
255  if (tbmres->ntuples >= 0)
256  node->exact_pages++;
257  else
258  node->lossy_pages++;
259 
260  /*
261  * Set rs_cindex to first slot to examine
262  */
263  scan->rs_cindex = 0;
264 
265  /* Adjust the prefetch target */
267  }
268  else
269  {
270  /*
271  * Continuing in previously obtained page; advance rs_cindex
272  */
273  scan->rs_cindex++;
274 
275 #ifdef USE_PREFETCH
276 
277  /*
278  * Try to prefetch at least a few pages even before we get to the
279  * second page if we don't stop reading after the first tuple.
280  */
281  if (!pstate)
282  {
283  if (node->prefetch_target < node->prefetch_maximum)
284  node->prefetch_target++;
285  }
286  else if (pstate->prefetch_target < node->prefetch_maximum)
287  {
288  /* take spinlock while updating shared state */
289  SpinLockAcquire(&pstate->mutex);
290  if (pstate->prefetch_target < node->prefetch_maximum)
291  pstate->prefetch_target++;
292  SpinLockRelease(&pstate->mutex);
293  }
294 #endif /* USE_PREFETCH */
295  }
296 
297  /*
298  * Out of range? If so, nothing more to look at on this page
299  */
300  if (scan->rs_cindex < 0 || scan->rs_cindex >= scan->rs_ntuples)
301  {
302  node->tbmres = tbmres = NULL;
303  continue;
304  }
305 
306  /*
307  * We issue prefetch requests *after* fetching the current page to try
308  * to avoid having prefetching interfere with the main I/O. Also, this
309  * should happen only when we have determined there is still something
310  * to do on the current page, else we may uselessly prefetch the same
311  * page we are just about to request for real.
312  */
313  BitmapPrefetch(node, scan);
314 
315  if (node->skip_fetch)
316  {
317  /*
318  * If we don't have to fetch the tuple, just return nulls.
319  */
320  ExecStoreAllNullTuple(slot);
321  }
322  else
323  {
324  /*
325  * Okay to fetch the tuple.
326  */
327  targoffset = scan->rs_vistuples[scan->rs_cindex];
328  dp = (Page) BufferGetPage(scan->rs_cbuf);
329  lp = PageGetItemId(dp, targoffset);
330  Assert(ItemIdIsNormal(lp));
331 
332  scan->rs_ctup.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
333  scan->rs_ctup.t_len = ItemIdGetLength(lp);
334  scan->rs_ctup.t_tableOid = scan->rs_rd->rd_id;
335  ItemPointerSet(&scan->rs_ctup.t_self, tbmres->blockno, targoffset);
336 
338 
339  /*
340  * Set up the result slot to point to this tuple. Note that the
341  * slot acquires a pin on the buffer.
342  */
343  ExecStoreTuple(&scan->rs_ctup,
344  slot,
345  scan->rs_cbuf,
346  false);
347 
348  /*
349  * If we are using lossy info, we have to recheck the qual
350  * conditions at every tuple.
351  */
352  if (tbmres->recheck)
353  {
354  econtext->ecxt_scantuple = slot;
355  if (!ExecQualAndReset(node->bitmapqualorig, econtext))
356  {
357  /* Fails recheck, so drop it and loop back for another */
358  InstrCountFiltered2(node, 1);
359  ExecClearTuple(slot);
360  continue;
361  }
362  }
363  }
364 
365  /* OK to return this tuple */
366  return slot;
367  }
368 
369  /*
370  * if we get here it means we are at the end of the scan..
371  */
372  return ExecClearTuple(slot);
373 }
static void BitmapPrefetch(BitmapHeapScanState *node, HeapScanDesc scan)
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:356
struct dsa_area * es_query_dsa
Definition: execnodes.h:565
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
ExprState * bitmapqualorig
Definition: execnodes.h:1441
static void BitmapAdjustPrefetchTarget(BitmapHeapScanState *node)
dsa_pointer tbm_prepare_shared_iterate(TIDBitmap *tbm)
Definition: tidbitmap.c:765
TupleTableSlot * ExecStoreAllNullTuple(TupleTableSlot *slot)
Definition: execTuples.c:548
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
static void bitgetpage(HeapScanDesc scan, TBMIterateResult *tbmres)
ExprContext * ps_ExprContext
Definition: execnodes.h:947
TIDBitmap * tbm
Definition: execnodes.h:1442
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1195
Relation ss_currentRelation
Definition: execnodes.h:1193
EState * state
Definition: execnodes.h:914
HeapTupleData rs_ctup
Definition: relscan.h:70
uint16 OffsetNumber
Definition: off.h:24
HeapTupleHeader t_data
Definition: htup.h:68
BlockNumber blockno
Definition: tidbitmap.h:42
PlanState ps
Definition: execnodes.h:1192
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
#define ERROR
Definition: elog.h:43
ParallelBitmapHeapState * pstate
Definition: execnodes.h:1459
ItemPointerData t_self
Definition: htup.h:65
#define pgstat_count_heap_fetch(rel)
Definition: pgstat.h:1286
#define outerPlanState(node)
Definition: execnodes.h:966
uint32 t_len
Definition: htup.h:64
static bool BitmapShouldInitializeSharedState(ParallelBitmapHeapState *pstate)
Oid t_tableOid
Definition: htup.h:66
dsa_pointer tbmiterator
Definition: execnodes.h:1404
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
TBMIterateResult * tbmres
Definition: execnodes.h:1444
Oid rd_id
Definition: rel.h:86
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define SpinLockRelease(lock)
Definition: spin.h:64
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Definition: executor.h:388
BlockNumber rs_nblocks
Definition: relscan.h:61
Relation rs_rd
Definition: relscan.h:49
dsa_pointer prefetch_iterator
Definition: execnodes.h:1405
static void BitmapAdjustPrefetchIterator(BitmapHeapScanState *node, TBMIterateResult *tbmres)
TBMIterateResult * tbm_iterate(TBMIterator *iterator)
Definition: tidbitmap.c:970
Buffer rs_cbuf
Definition: relscan.h:72
#define Assert(condition)
Definition: c.h:699
OffsetNumber rs_vistuples[MaxHeapTuplesPerPage]
Definition: relscan.h:79
#define ItemIdIsNormal(itemId)
Definition: itemid.h:98
#define InstrCountFiltered2(node, delta)
Definition: execnodes.h:979
#define VM_ALL_VISIBLE(r, b, v)
Definition: visibilitymap.h:32
TBMIterator * tbm_begin_iterate(TIDBitmap *tbm)
Definition: tidbitmap.c:688
TBMIterateResult * tbm_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1051
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:218
TBMSharedIterator * shared_tbmiterator
Definition: execnodes.h:1457
TBMIterator * tbmiterator
Definition: execnodes.h:1443
static void BitmapDoneInitializingSharedState(ParallelBitmapHeapState *pstate)
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1194
Definition: dsa.c:354
Node * MultiExecProcNode(PlanState *node)
Definition: execProcnode.c:483
TBMIterator * prefetch_iterator
Definition: execnodes.h:1451
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define elog
Definition: elog.h:219
TBMSharedIterator * tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp)
Definition: tidbitmap.c:1464
TBMSharedIterator * shared_prefetch_iterator
Definition: execnodes.h:1458
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:127

◆ BitmapHeapRecheck()

static bool BitmapHeapRecheck ( BitmapHeapScanState node,
TupleTableSlot slot 
)
static

Definition at line 707 of file nodeBitmapHeapscan.c.

References BitmapHeapScanState::bitmapqualorig, ExprContext::ecxt_scantuple, ExecQualAndReset(), ScanState::ps, PlanState::ps_ExprContext, and BitmapHeapScanState::ss.

Referenced by ExecBitmapHeapScan().

708 {
709  ExprContext *econtext;
710 
711  /*
712  * extract necessary information from index scan node
713  */
714  econtext = node->ss.ps.ps_ExprContext;
715 
716  /* Does the tuple meet the original qual conditions? */
717  econtext->ecxt_scantuple = slot;
718  return ExecQualAndReset(node->bitmapqualorig, econtext);
719 }
ExprState * bitmapqualorig
Definition: execnodes.h:1441
ExprContext * ps_ExprContext
Definition: execnodes.h:947
PlanState ps
Definition: execnodes.h:1192
static bool ExecQualAndReset(ExprState *state, ExprContext *econtext)
Definition: executor.h:388
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:218

◆ BitmapPrefetch()

static void BitmapPrefetch ( BitmapHeapScanState node,
HeapScanDesc  scan 
)
inlinestatic

Definition at line 602 of file nodeBitmapHeapscan.c.

References TBMIterateResult::blockno, BitmapHeapScanState::can_skip_fetch, MAIN_FORKNUM, ParallelBitmapHeapState::mutex, BitmapHeapScanState::prefetch_iterator, ParallelBitmapHeapState::prefetch_pages, BitmapHeapScanState::prefetch_pages, ParallelBitmapHeapState::prefetch_target, BitmapHeapScanState::prefetch_target, PrefetchBuffer(), BitmapHeapScanState::pstate, BitmapHeapScanState::pvmbuffer, TBMIterateResult::recheck, HeapScanDescData::rs_rd, BitmapHeapScanState::shared_prefetch_iterator, SpinLockAcquire, SpinLockRelease, BitmapHeapScanState::ss, ScanState::ss_currentRelation, tbm_end_iterate(), tbm_end_shared_iterate(), tbm_iterate(), tbm_shared_iterate(), BitmapHeapScanState::tbmres, and VM_ALL_VISIBLE.

Referenced by BitmapHeapNext().

603 {
604 #ifdef USE_PREFETCH
605  ParallelBitmapHeapState *pstate = node->pstate;
606 
607  if (pstate == NULL)
608  {
609  TBMIterator *prefetch_iterator = node->prefetch_iterator;
610 
611  if (prefetch_iterator)
612  {
613  while (node->prefetch_pages < node->prefetch_target)
614  {
615  TBMIterateResult *tbmpre = tbm_iterate(prefetch_iterator);
616  bool skip_fetch;
617 
618  if (tbmpre == NULL)
619  {
620  /* No more pages to prefetch */
621  tbm_end_iterate(prefetch_iterator);
622  node->prefetch_iterator = NULL;
623  break;
624  }
625  node->prefetch_pages++;
626 
627  /*
628  * If we expect not to have to actually read this heap page,
629  * skip this prefetch call, but continue to run the prefetch
630  * logic normally. (Would it be better not to increment
631  * prefetch_pages?)
632  *
633  * This depends on the assumption that the index AM will
634  * report the same recheck flag for this future heap page as
635  * it did for the current heap page; which is not a certainty
636  * but is true in many cases.
637  */
638  skip_fetch = (node->can_skip_fetch &&
639  (node->tbmres ? !node->tbmres->recheck : false) &&
641  tbmpre->blockno,
642  &node->pvmbuffer));
643 
644  if (!skip_fetch)
645  PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
646  }
647  }
648 
649  return;
650  }
651 
652  if (pstate->prefetch_pages < pstate->prefetch_target)
653  {
654  TBMSharedIterator *prefetch_iterator = node->shared_prefetch_iterator;
655 
656  if (prefetch_iterator)
657  {
658  while (1)
659  {
660  TBMIterateResult *tbmpre;
661  bool do_prefetch = false;
662  bool skip_fetch;
663 
664  /*
665  * Recheck under the mutex. If some other process has already
666  * done enough prefetching then we need not to do anything.
667  */
668  SpinLockAcquire(&pstate->mutex);
669  if (pstate->prefetch_pages < pstate->prefetch_target)
670  {
671  pstate->prefetch_pages++;
672  do_prefetch = true;
673  }
674  SpinLockRelease(&pstate->mutex);
675 
676  if (!do_prefetch)
677  return;
678 
679  tbmpre = tbm_shared_iterate(prefetch_iterator);
680  if (tbmpre == NULL)
681  {
682  /* No more pages to prefetch */
683  tbm_end_shared_iterate(prefetch_iterator);
684  node->shared_prefetch_iterator = NULL;
685  break;
686  }
687 
688  /* As above, skip prefetch if we expect not to need page */
689  skip_fetch = (node->can_skip_fetch &&
690  (node->tbmres ? !node->tbmres->recheck : false) &&
692  tbmpre->blockno,
693  &node->pvmbuffer));
694 
695  if (!skip_fetch)
696  PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, tbmpre->blockno);
697  }
698  }
699  }
700 #endif /* USE_PREFETCH */
701 }
void tbm_end_iterate(TBMIterator *iterator)
Definition: tidbitmap.c:1145
Relation ss_currentRelation
Definition: execnodes.h:1193
BlockNumber blockno
Definition: tidbitmap.h:42
#define SpinLockAcquire(lock)
Definition: spin.h:62
ParallelBitmapHeapState * pstate
Definition: execnodes.h:1459
TBMIterateResult * tbmres
Definition: execnodes.h:1444
#define SpinLockRelease(lock)
Definition: spin.h:64
void PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum)
Definition: bufmgr.c:529
Relation rs_rd
Definition: relscan.h:49
TBMIterateResult * tbm_iterate(TBMIterator *iterator)
Definition: tidbitmap.c:970
#define VM_ALL_VISIBLE(r, b, v)
Definition: visibilitymap.h:32
TBMIterateResult * tbm_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1051
TBMIterator * prefetch_iterator
Definition: execnodes.h:1451
TBMSharedIterator * shared_prefetch_iterator
Definition: execnodes.h:1458
void tbm_end_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1157

◆ BitmapShouldInitializeSharedState()

static bool BitmapShouldInitializeSharedState ( ParallelBitmapHeapState pstate)
static

Definition at line 987 of file nodeBitmapHeapscan.c.

References BM_INITIAL, BM_INPROGRESS, ConditionVariableCancelSleep(), ConditionVariableSleep(), ParallelBitmapHeapState::cv, ParallelBitmapHeapState::mutex, SpinLockAcquire, SpinLockRelease, ParallelBitmapHeapState::state, and WAIT_EVENT_PARALLEL_BITMAP_SCAN.

Referenced by BitmapHeapNext().

988 {
990 
991  while (1)
992  {
993  SpinLockAcquire(&pstate->mutex);
994  state = pstate->state;
995  if (pstate->state == BM_INITIAL)
996  pstate->state = BM_INPROGRESS;
997  SpinLockRelease(&pstate->mutex);
998 
999  /* Exit if bitmap is done, or if we're the leader. */
1000  if (state != BM_INPROGRESS)
1001  break;
1002 
1003  /* Wait for the leader to wake us up. */
1005  }
1006 
1008 
1009  return (state == BM_INITIAL);
1010 }
SharedBitmapState
Definition: execnodes.h:1382
#define SpinLockAcquire(lock)
Definition: spin.h:62
void ConditionVariableCancelSleep(void)
#define SpinLockRelease(lock)
Definition: spin.h:64
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
Definition: regguts.h:298
SharedBitmapState state
Definition: execnodes.h:1409
ConditionVariable cv
Definition: execnodes.h:1410

◆ ExecBitmapHeapEstimate()

void ExecBitmapHeapEstimate ( BitmapHeapScanState node,
ParallelContext pcxt 
)

Definition at line 1020 of file nodeBitmapHeapscan.c.

References add_size(), EState::es_snapshot, EstimateSnapshotSpace(), ParallelContext::estimator, offsetof, ScanState::ps, BitmapHeapScanState::pscan_len, shm_toc_estimate_chunk, shm_toc_estimate_keys, BitmapHeapScanState::ss, and PlanState::state.

Referenced by ExecParallelEstimate().

1022 {
1023  EState *estate = node->ss.ps.state;
1024 
1026  phs_snapshot_data),
1028 
1030  shm_toc_estimate_keys(&pcxt->estimator, 1);
1031 }
shm_toc_estimator estimator
Definition: parallel.h:41
Snapshot es_snapshot
Definition: execnodes.h:478
EState * state
Definition: execnodes.h:914
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
PlanState ps
Definition: execnodes.h:1192
Size EstimateSnapshotSpace(Snapshot snap)
Definition: snapmgr.c:2044
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
#define offsetof(type, field)
Definition: c.h:622

◆ ExecBitmapHeapInitializeDSM()

void ExecBitmapHeapInitializeDSM ( BitmapHeapScanState node,
ParallelContext pcxt 
)

Definition at line 1040 of file nodeBitmapHeapscan.c.

References BM_INITIAL, ConditionVariableInit(), ParallelBitmapHeapState::cv, EState::es_query_dsa, EState::es_snapshot, ParallelBitmapHeapState::mutex, ParallelBitmapHeapState::phs_snapshot_data, PlanState::plan, Plan::plan_node_id, ParallelBitmapHeapState::prefetch_iterator, ParallelBitmapHeapState::prefetch_pages, ParallelBitmapHeapState::prefetch_target, ScanState::ps, BitmapHeapScanState::pscan_len, BitmapHeapScanState::pstate, SerializeSnapshot(), shm_toc_allocate(), shm_toc_insert(), SpinLockInit, BitmapHeapScanState::ss, PlanState::state, ParallelBitmapHeapState::state, ParallelBitmapHeapState::tbmiterator, and ParallelContext::toc.

Referenced by ExecParallelInitializeDSM().

1042 {
1043  ParallelBitmapHeapState *pstate;
1044  EState *estate = node->ss.ps.state;
1045  dsa_area *dsa = node->ss.ps.state->es_query_dsa;
1046 
1047  /* If there's no DSA, there are no workers; initialize nothing. */
1048  if (dsa == NULL)
1049  return;
1050 
1051  pstate = shm_toc_allocate(pcxt->toc, node->pscan_len);
1052 
1053  pstate->tbmiterator = 0;
1054  pstate->prefetch_iterator = 0;
1055 
1056  /* Initialize the mutex */
1057  SpinLockInit(&pstate->mutex);
1058  pstate->prefetch_pages = 0;
1059  pstate->prefetch_target = 0;
1060  pstate->state = BM_INITIAL;
1061 
1062  ConditionVariableInit(&pstate->cv);
1064 
1065  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id, pstate);
1066  node->pstate = pstate;
1067 }
struct dsa_area * es_query_dsa
Definition: execnodes.h:565
#define SpinLockInit(lock)
Definition: spin.h:60
int plan_node_id
Definition: plannodes.h:145
Snapshot es_snapshot
Definition: execnodes.h:478
EState * state
Definition: execnodes.h:914
PlanState ps
Definition: execnodes.h:1192
void ConditionVariableInit(ConditionVariable *cv)
ParallelBitmapHeapState * pstate
Definition: execnodes.h:1459
void SerializeSnapshot(Snapshot snapshot, char *start_address)
Definition: snapmgr.c:2068
dsa_pointer tbmiterator
Definition: execnodes.h:1404
Plan * plan
Definition: execnodes.h:912
dsa_pointer prefetch_iterator
Definition: execnodes.h:1405
SharedBitmapState state
Definition: execnodes.h:1409
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
char phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER]
Definition: execnodes.h:1411
Definition: dsa.c:354
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
ConditionVariable cv
Definition: execnodes.h:1410
shm_toc * toc
Definition: parallel.h:44

◆ ExecBitmapHeapInitializeWorker()

void ExecBitmapHeapInitializeWorker ( BitmapHeapScanState node,
ParallelWorkerContext pwcxt 
)

Definition at line 1105 of file nodeBitmapHeapscan.c.

References Assert, EState::es_query_dsa, heap_update_snapshot(), ParallelBitmapHeapState::phs_snapshot_data, PlanState::plan, Plan::plan_node_id, ScanState::ps, BitmapHeapScanState::pstate, RestoreSnapshot(), shm_toc_lookup(), BitmapHeapScanState::ss, ScanState::ss_currentScanDesc, PlanState::state, and ParallelWorkerContext::toc.

Referenced by ExecParallelInitializeWorker().

1107 {
1108  ParallelBitmapHeapState *pstate;
1109  Snapshot snapshot;
1110 
1111  Assert(node->ss.ps.state->es_query_dsa != NULL);
1112 
1113  pstate = shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, false);
1114  node->pstate = pstate;
1115 
1116  snapshot = RestoreSnapshot(pstate->phs_snapshot_data);
1117  heap_update_snapshot(node->ss.ss_currentScanDesc, snapshot);
1118 }
struct dsa_area * es_query_dsa
Definition: execnodes.h:565
Snapshot RestoreSnapshot(char *start_address)
Definition: snapmgr.c:2127
void heap_update_snapshot(HeapScanDesc scan, Snapshot snapshot)
Definition: heapam.c:1801
int plan_node_id
Definition: plannodes.h:145
EState * state
Definition: execnodes.h:914
PlanState ps
Definition: execnodes.h:1192
ParallelBitmapHeapState * pstate
Definition: execnodes.h:1459
Plan * plan
Definition: execnodes.h:912
#define Assert(condition)
Definition: c.h:699
char phs_snapshot_data[FLEXIBLE_ARRAY_MEMBER]
Definition: execnodes.h:1411
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1194
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232

◆ ExecBitmapHeapReInitializeDSM()

void ExecBitmapHeapReInitializeDSM ( BitmapHeapScanState node,
ParallelContext pcxt 
)

Definition at line 1076 of file nodeBitmapHeapscan.c.

References BM_INITIAL, DsaPointerIsValid, EState::es_query_dsa, InvalidDsaPointer, ParallelBitmapHeapState::prefetch_iterator, ScanState::ps, BitmapHeapScanState::pstate, BitmapHeapScanState::ss, PlanState::state, ParallelBitmapHeapState::state, tbm_free_shared_area(), and ParallelBitmapHeapState::tbmiterator.

Referenced by ExecParallelReInitializeDSM().

1078 {
1079  ParallelBitmapHeapState *pstate = node->pstate;
1080  dsa_area *dsa = node->ss.ps.state->es_query_dsa;
1081 
1082  /* If there's no DSA, there are no workers; do nothing. */
1083  if (dsa == NULL)
1084  return;
1085 
1086  pstate->state = BM_INITIAL;
1087 
1088  if (DsaPointerIsValid(pstate->tbmiterator))
1089  tbm_free_shared_area(dsa, pstate->tbmiterator);
1090 
1091  if (DsaPointerIsValid(pstate->prefetch_iterator))
1093 
1094  pstate->tbmiterator = InvalidDsaPointer;
1096 }
struct dsa_area * es_query_dsa
Definition: execnodes.h:565
#define InvalidDsaPointer
Definition: dsa.h:78
EState * state
Definition: execnodes.h:914
PlanState ps
Definition: execnodes.h:1192
ParallelBitmapHeapState * pstate
Definition: execnodes.h:1459
dsa_pointer tbmiterator
Definition: execnodes.h:1404
void tbm_free_shared_area(dsa_area *dsa, dsa_pointer dp)
Definition: tidbitmap.c:340
dsa_pointer prefetch_iterator
Definition: execnodes.h:1405
SharedBitmapState state
Definition: execnodes.h:1409
#define DsaPointerIsValid(x)
Definition: dsa.h:81
Definition: dsa.c:354

◆ ExecBitmapHeapScan()

static TupleTableSlot* ExecBitmapHeapScan ( PlanState pstate)
static

Definition at line 726 of file nodeBitmapHeapscan.c.

References BitmapHeapNext(), BitmapHeapRecheck(), castNode, ExecScan(), and BitmapHeapScanState::ss.

Referenced by ExecInitBitmapHeapScan().

727 {
729 
730  return ExecScan(&node->ss,
733 }
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:121
static TupleTableSlot * BitmapHeapNext(BitmapHeapScanState *node)
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:422
static bool BitmapHeapRecheck(BitmapHeapScanState *node, TupleTableSlot *slot)
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:421

◆ ExecEndBitmapHeapScan()

void ExecEndBitmapHeapScan ( BitmapHeapScanState node)

Definition at line 787 of file nodeBitmapHeapscan.c.

References ExecClearTuple(), ExecCloseScanRelation(), ExecEndNode(), ExecFreeExprContext(), heap_endscan(), InvalidBuffer, outerPlanState, BitmapHeapScanState::prefetch_iterator, ScanState::ps, PlanState::ps_ResultTupleSlot, BitmapHeapScanState::pvmbuffer, ReleaseBuffer(), BitmapHeapScanState::shared_prefetch_iterator, BitmapHeapScanState::shared_tbmiterator, BitmapHeapScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, ScanState::ss_ScanTupleSlot, BitmapHeapScanState::tbm, tbm_end_iterate(), tbm_end_shared_iterate(), tbm_free(), BitmapHeapScanState::tbmiterator, and BitmapHeapScanState::vmbuffer.

Referenced by ExecEndNode().

788 {
789  Relation relation;
790  HeapScanDesc scanDesc;
791 
792  /*
793  * extract information from the node
794  */
795  relation = node->ss.ss_currentRelation;
796  scanDesc = node->ss.ss_currentScanDesc;
797 
798  /*
799  * Free the exprcontext
800  */
801  ExecFreeExprContext(&node->ss.ps);
802 
803  /*
804  * clear out tuple table slots
805  */
808 
809  /*
810  * close down subplans
811  */
813 
814  /*
815  * release bitmaps and buffers if any
816  */
817  if (node->tbmiterator)
819  if (node->prefetch_iterator)
821  if (node->tbm)
822  tbm_free(node->tbm);
823  if (node->shared_tbmiterator)
825  if (node->shared_prefetch_iterator)
827  if (node->vmbuffer != InvalidBuffer)
828  ReleaseBuffer(node->vmbuffer);
829  if (node->pvmbuffer != InvalidBuffer)
830  ReleaseBuffer(node->pvmbuffer);
831 
832  /*
833  * close heap scan
834  */
835  heap_endscan(scanDesc);
836 
837  /*
838  * close the heap relation.
839  */
840  ExecCloseScanRelation(relation);
841 }
void tbm_end_iterate(TBMIterator *iterator)
Definition: tidbitmap.c:1145
void heap_endscan(HeapScanDesc scan)
Definition: heapam.c:1572
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:538
TIDBitmap * tbm
Definition: execnodes.h:1442
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
#define InvalidBuffer
Definition: buf.h:25
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1195
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
Relation ss_currentRelation
Definition: execnodes.h:1193
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:566
PlanState ps
Definition: execnodes.h:1192
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:946
#define outerPlanState(node)
Definition: execnodes.h:966
void tbm_free(TIDBitmap *tbm)
Definition: tidbitmap.c:321
void ExecCloseScanRelation(Relation scanrel)
Definition: execUtils.c:701
TBMSharedIterator * shared_tbmiterator
Definition: execnodes.h:1457
TBMIterator * tbmiterator
Definition: execnodes.h:1443
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1194
TBMIterator * prefetch_iterator
Definition: execnodes.h:1451
TBMSharedIterator * shared_prefetch_iterator
Definition: execnodes.h:1458
void tbm_end_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1157

◆ ExecInitBitmapHeapScan()

BitmapHeapScanState* ExecInitBitmapHeapScan ( BitmapHeapScan node,
EState estate,
int  eflags 
)

Definition at line 850 of file nodeBitmapHeapscan.c.

References Assert, BitmapHeapScan::bitmapqualorig, BitmapHeapScanState::can_skip_fetch, ComputeIoConcurrency(), effective_io_concurrency, EState::es_snapshot, BitmapHeapScanState::exact_pages, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignScanProjectionInfo(), ExecBitmapHeapScan(), ExecInitNode(), ExecInitQual(), ExecInitResultTupleSlotTL(), ExecInitScanTupleSlot(), ExecOpenScanRelation(), PlanState::ExecProcNode, get_tablespace_io_concurrency(), heap_beginscan_bm(), BitmapHeapScanState::initialized, InvalidBuffer, IsMVCCSnapshot, BitmapHeapScanState::lossy_pages, makeNode, NIL, outerPlan, outerPlanState, Scan::plan, PlanState::plan, BitmapHeapScanState::prefetch_iterator, BitmapHeapScanState::prefetch_maximum, BitmapHeapScanState::prefetch_pages, BitmapHeapScanState::prefetch_target, ScanState::ps, BitmapHeapScanState::pscan_len, BitmapHeapScanState::pstate, BitmapHeapScanState::pvmbuffer, Plan::qual, PlanState::qual, RelationData::rd_rel, RelationGetDescr, rint(), BitmapHeapScan::scan, Scan::scanrelid, BitmapHeapScanState::shared_prefetch_iterator, BitmapHeapScanState::shared_tbmiterator, BitmapHeapScanState::skip_fetch, BitmapHeapScanState::ss, PlanState::state, target_prefetch_pages, Plan::targetlist, BitmapHeapScanState::tbm, BitmapHeapScanState::tbmiterator, BitmapHeapScanState::tbmres, and BitmapHeapScanState::vmbuffer.

Referenced by ExecInitNode().

851 {
852  BitmapHeapScanState *scanstate;
853  Relation currentRelation;
854  int io_concurrency;
855 
856  /* check for unsupported flags */
857  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
858 
859  /*
860  * Assert caller didn't ask for an unsafe snapshot --- see comments at
861  * head of file.
862  */
864 
865  /*
866  * create state structure
867  */
868  scanstate = makeNode(BitmapHeapScanState);
869  scanstate->ss.ps.plan = (Plan *) node;
870  scanstate->ss.ps.state = estate;
871  scanstate->ss.ps.ExecProcNode = ExecBitmapHeapScan;
872 
873  scanstate->tbm = NULL;
874  scanstate->tbmiterator = NULL;
875  scanstate->tbmres = NULL;
876  scanstate->skip_fetch = false;
877  scanstate->vmbuffer = InvalidBuffer;
878  scanstate->pvmbuffer = InvalidBuffer;
879  scanstate->exact_pages = 0;
880  scanstate->lossy_pages = 0;
881  scanstate->prefetch_iterator = NULL;
882  scanstate->prefetch_pages = 0;
883  scanstate->prefetch_target = 0;
884  /* may be updated below */
886  scanstate->pscan_len = 0;
887  scanstate->initialized = false;
888  scanstate->shared_tbmiterator = NULL;
889  scanstate->shared_prefetch_iterator = NULL;
890  scanstate->pstate = NULL;
891 
892  /*
893  * We can potentially skip fetching heap pages if we do not need any
894  * columns of the table, either for checking non-indexable quals or for
895  * returning data. This test is a bit simplistic, as it checks the
896  * stronger condition that there's no qual or return tlist at all. But in
897  * most cases it's probably not worth working harder than that.
898  */
899  scanstate->can_skip_fetch = (node->scan.plan.qual == NIL &&
900  node->scan.plan.targetlist == NIL);
901 
902  /*
903  * Miscellaneous initialization
904  *
905  * create expression context for node
906  */
907  ExecAssignExprContext(estate, &scanstate->ss.ps);
908 
909  /*
910  * open the base relation and acquire appropriate lock on it.
911  */
912  currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
913 
914  /*
915  * initialize child nodes
916  *
917  * We do this after ExecOpenScanRelation because the child nodes will open
918  * indexscans on our relation's indexes, and we want to be sure we have
919  * acquired a lock on the relation first.
920  */
921  outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags);
922 
923  /*
924  * get the scan type from the relation descriptor.
925  */
926  ExecInitScanTupleSlot(estate, &scanstate->ss,
927  RelationGetDescr(currentRelation));
928 
929 
930  /*
931  * Initialize result slot, type and projection.
932  */
933  ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
934  ExecAssignScanProjectionInfo(&scanstate->ss);
935 
936  /*
937  * initialize child expressions
938  */
939  scanstate->ss.ps.qual =
940  ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
941  scanstate->bitmapqualorig =
942  ExecInitQual(node->bitmapqualorig, (PlanState *) scanstate);
943 
944  /*
945  * Determine the maximum for prefetch_target. If the tablespace has a
946  * specific IO concurrency set, use that to compute the corresponding
947  * maximum value; otherwise, we already initialized to the value computed
948  * by the GUC machinery.
949  */
950  io_concurrency =
951  get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
952  if (io_concurrency != effective_io_concurrency)
953  {
954  double maximum;
955 
956  if (ComputeIoConcurrency(io_concurrency, &maximum))
957  scanstate->prefetch_maximum = rint(maximum);
958  }
959 
960  scanstate->ss.ss_currentRelation = currentRelation;
961 
962  /*
963  * Even though we aren't going to do a conventional seqscan, it is useful
964  * to create a HeapScanDesc --- most of the fields in it are usable.
965  */
966  scanstate->ss.ss_currentScanDesc = heap_beginscan_bm(currentRelation,
967  estate->es_snapshot,
968  0,
969  NULL);
970 
971  /*
972  * all done.
973  */
974  return scanstate;
975 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:147
int target_prefetch_pages
Definition: bufmgr.c:129
Plan plan
Definition: plannodes.h:342
ExprState * bitmapqualorig
Definition: execnodes.h:1441
Index scanrelid
Definition: plannodes.h:343
#define RelationGetDescr(relation)
Definition: rel.h:433
TIDBitmap * tbm
Definition: execnodes.h:1442
#define InvalidBuffer
Definition: buf.h:25
int get_tablespace_io_concurrency(Oid spcid)
Definition: spccache.c:215
Snapshot es_snapshot
Definition: execnodes.h:478
Relation ss_currentRelation
Definition: execnodes.h:1193
EState * state
Definition: execnodes.h:914
Form_pg_class rd_rel
Definition: rel.h:84
int effective_io_concurrency
Definition: bufmgr.c:112
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:205
bool ComputeIoConcurrency(int io_concurrency, double *target)
Definition: bufmgr.c:467
PlanState ps
Definition: execnodes.h:1192
static TupleTableSlot * ExecBitmapHeapScan(PlanState *pstate)
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:235
ParallelBitmapHeapState * pstate
Definition: execnodes.h:1459
Relation ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
Definition: execUtils.c:643
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define outerPlanState(node)
Definition: execnodes.h:966
double rint(double x)
Definition: rint.c:22
List * bitmapqualorig
Definition: plannodes.h:477
TBMIterateResult * tbmres
Definition: execnodes.h:1444
#define outerPlan(node)
Definition: plannodes.h:176
HeapScanDesc heap_beginscan_bm(Relation relation, Snapshot snapshot, int nkeys, ScanKey key)
Definition: heapam.c:1432
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:918
void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
Definition: execTuples.c:890
Plan * plan
Definition: execnodes.h:912
#define makeNode(_type_)
Definition: nodes.h:565
#define Assert(condition)
Definition: c.h:699
#define IsMVCCSnapshot(snapshot)
Definition: tqual.h:31
#define EXEC_FLAG_MARK
Definition: executor.h:61
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:428
TBMSharedIterator * shared_tbmiterator
Definition: execnodes.h:1457
TBMIterator * tbmiterator
Definition: execnodes.h:1443
List * targetlist
Definition: plannodes.h:146
ExprState * qual
Definition: execnodes.h:930
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1194
TBMIterator * prefetch_iterator
Definition: execnodes.h:1451
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
Definition: execTuples.c:915
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
TBMSharedIterator * shared_prefetch_iterator
Definition: execnodes.h:1458

◆ ExecReScanBitmapHeapScan()

void ExecReScanBitmapHeapScan ( BitmapHeapScanState node)

Definition at line 740 of file nodeBitmapHeapscan.c.

References PlanState::chgParam, ExecReScan(), ExecScanReScan(), heap_rescan(), BitmapHeapScanState::initialized, InvalidBuffer, outerPlan, outerPlanState, BitmapHeapScanState::prefetch_iterator, BitmapHeapScanState::pvmbuffer, ReleaseBuffer(), BitmapHeapScanState::shared_prefetch_iterator, BitmapHeapScanState::shared_tbmiterator, BitmapHeapScanState::ss, ScanState::ss_currentScanDesc, BitmapHeapScanState::tbm, tbm_end_iterate(), tbm_end_shared_iterate(), tbm_free(), BitmapHeapScanState::tbmiterator, BitmapHeapScanState::tbmres, and BitmapHeapScanState::vmbuffer.

Referenced by ExecReScan().

741 {
743 
744  /* rescan to release any page pin */
745  heap_rescan(node->ss.ss_currentScanDesc, NULL);
746 
747  /* release bitmaps and buffers if any */
748  if (node->tbmiterator)
750  if (node->prefetch_iterator)
752  if (node->shared_tbmiterator)
754  if (node->shared_prefetch_iterator)
756  if (node->tbm)
757  tbm_free(node->tbm);
758  if (node->vmbuffer != InvalidBuffer)
759  ReleaseBuffer(node->vmbuffer);
760  if (node->pvmbuffer != InvalidBuffer)
761  ReleaseBuffer(node->pvmbuffer);
762  node->tbm = NULL;
763  node->tbmiterator = NULL;
764  node->tbmres = NULL;
765  node->prefetch_iterator = NULL;
766  node->initialized = false;
767  node->shared_tbmiterator = NULL;
768  node->shared_prefetch_iterator = NULL;
769  node->vmbuffer = InvalidBuffer;
770  node->pvmbuffer = InvalidBuffer;
771 
772  ExecScanReScan(&node->ss);
773 
774  /*
775  * if chgParam of subnode is not null then plan will be re-scanned by
776  * first ExecProcNode.
777  */
778  if (outerPlan->chgParam == NULL)
779  ExecReScan(outerPlan);
780 }
void tbm_end_iterate(TBMIterator *iterator)
Definition: tidbitmap.c:1145
TIDBitmap * tbm
Definition: execnodes.h:1442
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
#define InvalidBuffer
Definition: buf.h:25
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define outerPlanState(node)
Definition: execnodes.h:966
void tbm_free(TIDBitmap *tbm)
Definition: tidbitmap.c:321
void heap_rescan(HeapScanDesc scan, ScanKey key)
Definition: heapam.c:1528
TBMIterateResult * tbmres
Definition: execnodes.h:1444
Bitmapset * chgParam
Definition: execnodes.h:941
#define outerPlan(node)
Definition: plannodes.h:176
TBMSharedIterator * shared_tbmiterator
Definition: execnodes.h:1457
TBMIterator * tbmiterator
Definition: execnodes.h:1443
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1194
TBMIterator * prefetch_iterator
Definition: execnodes.h:1451
void ExecScanReScan(ScanState *node)
Definition: execScan.c:262
TBMSharedIterator * shared_prefetch_iterator
Definition: execnodes.h:1458
void tbm_end_shared_iterate(TBMSharedIterator *iterator)
Definition: tidbitmap.c:1157