Access Methods (AMs) are PostgreSQL’s abstraction for how data is stored and retrieved. Every table is managed by a Table AM (almost always the heap), and every index is managed by an Index AM (B-tree, hash, GiST, GIN, BRIN, or SP-GiST). PostgreSQL 12+ exposes both as pluggable APIs, letting extensions provide entirely new storage engines or index types without modifying the core.
PostgreSQL separates what the executor wants (scan a table, insert a tuple, look up a key) from how the AM accomplishes it. Two callback structs sit at the centre of this design:
| Layer | Callback Struct | Header | Purpose |
|---|---|---|---|
| Table AM | TableAmRoutine |
src/include/access/tableam.h |
Scan, fetch, insert, update, delete, vacuum for heap-like stores |
| Index AM | IndexAmRoutine |
src/include/access/amapi.h |
Build, insert, scan, vacuum for index structures |
Each AM registers a handler function (e.g., heap_tableam_handler,
bthandler) that returns a pointer to the filled-in routine struct. The
executor then calls through these function pointers, never knowing which
concrete AM is behind the relation.
Executor
|
+------------+------------+
| |
table_scan_*() index_scan_*()
| |
+-------v--------+ +--------v--------+
| TableAmRoutine | | IndexAmRoutine |
| (tableam.h) | | (amapi.h) |
+-------+---------+ +--------+---------+
| |
+---------+ +---------+---------+---------+---------+
| | | | | |
Heap AM B-tree Hash GiST GIN BRIN
(heap/) (nbtree/) (hash/) (gist/) (gin/) (brin/)
|
SP-GiST
(spgist/)
| File | Purpose |
|---|---|
src/include/access/amapi.h |
IndexAmRoutine definition and all index AM callback typedefs |
src/include/access/tableam.h |
TableAmRoutine definition and table AM callback typedefs |
src/backend/access/table/tableam.c |
Generic table AM dispatcher functions |
src/backend/access/table/tableamapi.c |
GetTableAmRoutine() – resolves handler OID to routine |
src/backend/access/index/ |
Generic index AM utilities (amapi.c, indexam.c, genam.c) |
src/include/access/genam.h |
IndexScanDesc and generic index scan definitions |
src/include/access/relscan.h |
TableScanDesc base struct |
table_beginscan() calls scan_begin in the TableAmRoutine.HeapScanDescData (which embeds a TableScanDescData).table_scan_getnextslot() calls scan_getnextslot to fetch tuples.HeapTupleSatisfiesVisibility().index_beginscan() calls ambeginscan in the IndexAmRoutine.btbeginscan() allocates BTScanOpaqueData.index_getnext_slot() calls amgettuple, which walks the tree and
returns TIDs. The executor then calls index_fetch_tuple on the table AM
to retrieve the heap tuple.The planner calls amcostestimate to get selectivity and cost for each
potential index path. Flags like amcanorder, amcanunique, and
amsearcharray on IndexAmRoutine tell the planner which plan shapes are
valid.
| Section | Topic |
|---|---|
| Heap AM | Heap storage, page layout, HOT updates, TOAST |
| B-tree | Lehman-Yao B+tree, deduplication, page splits |
| Hash Index | Linear hashing, overflow pages |
| GiST | Generalized Search Tree for spatial and custom types |
| GIN | Inverted index, fast update buffer, posting lists |
| BRIN | Block Range Index for large naturally-ordered tables |
| SP-GiST | Space-partitioned trees: k-d trees, radix tries |
| Table AM API | Pluggable storage API deep dive |
PageHeaderData, ItemIdData) is the foundation for the heap AM.TableAmRoutine and IndexAmRoutine interfaces.heapam_visibility.c determine which tuples the heap AM returns. Index AMs rely on the table AM for final visibility checks.*_xlog.c module.