0
点赞
收藏
分享

微信扫一扫

PostgreSQL数据库TableAM——HeapAM Scans


PostgreSQL数据库TableAM——HeapAM Scans_数据库

static const TableAmRoutine heapam_methods = {
.type = T_TableAmRoutine,
.slot_callbacks = heapam_slot_callbacks,

.scan_begin = heap_beginscan,
.scan_end = heap_endscan,
.scan_rescan = heap_rescan,
.scan_getnextslot = heap_getnextslot,

.parallelscan_estimate = table_block_parallelscan_estimate,
.parallelscan_initialize = table_block_parallelscan_initialize,
.parallelscan_reinitialize = table_block_parallelscan_reinitialize,
...
}

heap_beginscan

heap_beginscan函数用于初始化HeapScanDescData结构体,ParallelTableScanDesc形参在ExecGather函数中ExecSeqScanInitializeDSM函数会调用TableAM提供的table_beginscan_parallel函数,该函数中会申请ParallelTableScanDesc内存,而串行scan时,heap_beginscan函数在SeqNext函数执行时调用,但是ParallelTableScanDesc形参为null。

TableScanDesc heap_beginscan(Relation relation, Snapshot snapshot, int nkeys, ScanKey key,
ParallelTableScanDesc parallel_scan, uint32 flags) {
RelationIncrementReferenceCount(relation);
HeapScanDesc scan = (HeapScanDesc) palloc(sizeof(HeapScanDescData));
scan->rs_base.rs_rd = relation; scan->rs_base.rs_snapshot = snapshot; scan->rs_base.rs_nkeys = nkeys;
scan->rs_base.rs_flags = flags; scan->rs_base.rs_parallel = parallel_scan; scan->rs_strategy = NULL; /* set in initscan */
if (!(snapshot && IsMVCCSnapshot(snapshot))) scan->rs_base.rs_flags &= ~SO_ALLOW_PAGEMODE; /* Disable page-at-a-time mode if it's not a MVCC-safe snapshot. */
if (scan->rs_base.rs_flags & (SO_TYPE_SEQSCAN | SO_TYPE_SAMPLESCAN)){
/* Ensure a missing snapshot is noticed reliably, even if the isolation mode means predicate locking isn't performed (and therefore the snapshot isn't used here). */
PredicateLockRelation(relation, snapshot);
}
scan->rs_ctup.t_tableOid = RelationGetRelid(relation); /* we only need to set this up once */
/* we do this here instead of in initscan() because heap_rescan also calls initscan() and we don't want to allocate memory again */
if (nkeys > 0) scan->rs_base.rs_key = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
else scan->rs_base.rs_key = NULL;

initscan(scan, key, false);

return (TableScanDesc) scan;
}

PostgreSQL数据库TableAM——HeapAM Scans_oracle_02

heap_endscan

void heap_endscan(TableScanDesc sscan) {
HeapScanDesc scan = (HeapScanDesc) sscan;
/* unpin scan buffers */
if (BufferIsValid(scan->rs_cbuf)) ReleaseBuffer(scan->rs_cbuf);
RelationDecrementReferenceCount(scan->rs_base.rs_rd);
if (scan->rs_base.rs_key) pfree(scan->rs_base.rs_key);
if (scan->rs_strategy != NULL) FreeAccessStrategy(scan->rs_strategy);
if (scan->rs_base.rs_flags & SO_TEMP_SNAPSHOT)
UnregisterSnapshot(scan->rs_base.rs_snapshot);
pfree(scan);
}

heap_getnextslot

heap_getnext函数获取tuple数据元组,分为两种页扫描模式:如果scan->rs_base.rs_flags为SO_ALLOW_PAGEMODE即扫描所有满足可见性的记录heapgettup_pagemode,否则扫描所有记录heapgettup。

typedef enum ScanDirection {
BackwardScanDirection = -1,
NoMovementScanDirection = 0, // re-fetch the tuple indicated by scan->rs_ctup
ForwardScanDirection = 1
} ScanDirection;

HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction) {
HeapScanDesc scan = (HeapScanDesc) sscan;
if (unlikely(sscan->rs_rd->rd_tableam != GetHeapamTableAmRoutine()))
ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg_internal("only heap AM is supported")));
if (scan->rs_base.rs_flags & SO_ALLOW_PAGEMODE)
heapgettup_pagemode(scan, direction, scan->rs_base.rs_nkeys, scan->rs_base.rs_key);
else
heapgettup(scan, direction, scan->rs_base.rs_nkeys, scan->rs_base.rs_key);

if (scan->rs_ctup.t_data == NULL) { return NULL } // returning EOS

pgstat_count_heap_getnext(scan->rs_base.rs_rd);
return &scan->rs_ctup;
}

PostgreSQL数据库TableAM——HeapAM Scans_oracle_03


举报

相关推荐

0 条评论