heap
Core table AM
内置 heap 表访问方法将元组存储、可见性、扫描、索引获取和维护操作集成到 PostgreSQL 中。
当前查看 PostgreSQL 18.6。
说明
内置 heap 表访问方法将元组存储、可见性、扫描、索引获取和维护操作集成到 PostgreSQL 中。
- 接口类别
- 表访问方法
- 处理函数或例程
- heapam_methods
- 记录的回调
- 43
接口与能力边界
矩阵记录此源码构建实际注册的回调。注册表明实现了相应接口钩子;操作是否允许还取决于选项、查询形式、权限和提供方规则。
下方保留同版本完整手册,包括配置、约束和示例。不声称已进行运行时能力测试。
堆存储、可见性与 WAL
此清单从 PostgreSQL 12 引入的 Table AM 接口开始。不会将更早版本的 PostgreSQL 堆存储重新标为 Table AM 实现。
堆可见性遵循 PostgreSQL 快照。WAL 和崩溃恢复行为取决于关系的持久性;临时表、无日志表与永久表不同。索引访问方法与表存储接口分开。
核心源码中注册的实现
{
.type = T_TableAmRoutine,
.slot_callbacks = heapam_slot_callbacks,
.scan_begin = heap_beginscan,
.scan_end = heap_endscan,
.scan_rescan = heap_rescan,
.scan_getnextslot = heap_getnextslot,
.scan_set_tidrange = heap_set_tidrange,
.scan_getnextslot_tidrange = heap_getnextslot_tidrange,
.parallelscan_estimate = table_block_parallelscan_estimate,
.parallelscan_initialize = table_block_parallelscan_initialize,
.parallelscan_reinitialize = table_block_parallelscan_reinitialize,
.index_fetch_begin = heapam_index_fetch_begin,
.index_fetch_reset = heapam_index_fetch_reset,
.index_fetch_end = heapam_index_fetch_end,
.index_fetch_tuple = heapam_index_fetch_tuple,
.tuple_insert = heapam_tuple_insert,
.tuple_insert_speculative = heapam_tuple_insert_speculative,
.tuple_complete_speculative = heapam_tuple_complete_speculative,
.multi_insert = heap_multi_insert,
.tuple_delete = heapam_tuple_delete,
.tuple_update = heapam_tuple_update,
.tuple_lock = heapam_tuple_lock,
.tuple_fetch_row_version = heapam_fetch_row_version,
.tuple_get_latest_tid = heap_get_latest_tid,
.tuple_tid_valid = heapam_tuple_tid_valid,
.tuple_satisfies_snapshot = heapam_tuple_satisfies_snapshot,
.index_delete_tuples = heap_index_delete_tuples,
.relation_set_new_filelocator = heapam_relation_set_new_filelocator,
.relation_nontransactional_truncate = heapam_relation_nontransactional_truncate,
.relation_copy_data = heapam_relation_copy_data,
.relation_copy_for_cluster = heapam_relation_copy_for_cluster,
.relation_vacuum = heap_vacuum_rel,
.scan_analyze_next_block = heapam_scan_analyze_next_block,
.scan_analyze_next_tuple = heapam_scan_analyze_next_tuple,
.index_build_range_scan = heapam_index_build_range_scan,
.index_validate_scan = heapam_index_validate_scan,
.relation_size = table_block_relation_size,
.relation_needs_toast_table = heapam_relation_needs_toast_table,
.relation_toast_am = heapam_relation_toast_am,
.relation_fetch_toast_slice = heap_fetch_toast_slice,
.relation_estimate_size = heapam_estimate_rel_size,
.scan_bitmap_next_tuple = heapam_scan_bitmap_next_tuple,
.scan_sample_next_block = heapam_scan_sample_next_block,
.scan_sample_next_tuple = heapam_scan_sample_next_tuple
}注册的接口处理函数
| 接口操作 | 源码观察 | 回调 | 实现 |
|---|---|---|---|
| 元组槽 | 已注册处理函数;适用条件限制 | slot_callbacks | heapam_slot_callbacks |
| 开始扫描 | 已注册处理函数;适用条件限制 | scan_begin | heap_beginscan |
| 初始化并行扫描 | 已注册处理函数;适用条件限制 | parallelscan_initialize | table_block_parallelscan_initialize |
| 开始索引查找 | 已注册处理函数;适用条件限制 | index_fetch_begin | heapam_index_fetch_begin |
| 获取指定元组 | 已注册处理函数;适用条件限制 | index_fetch_tuple | heapam_index_fetch_tuple |
| 插入元组 | 已注册处理函数;适用条件限制 | tuple_insert | heapam_tuple_insert |
| 更新元组 | 已注册处理函数;适用条件限制 | tuple_update | heapam_tuple_update |
| 删除元组 | 已注册处理函数;适用条件限制 | tuple_delete | heapam_tuple_delete |
| 对关系执行 VACUUM | 已注册处理函数;适用条件限制 | relation_vacuum | heap_vacuum_rel |
| 分析数据块 | 已注册处理函数;适用条件限制 | scan_analyze_next_block | heapam_scan_analyze_next_block |
| TOAST 判定 | 已注册处理函数;适用条件限制 | relation_needs_toast_table | heapam_relation_needs_toast_table |
手册定义
第 62 章. Table Access Method Interface Definition
本章说明 PostgreSQL 核心系统与管理表存储的表访问方法之间的接口。除这里规定的内容之外,核心系统对这些访问方法知之甚少,因此可以通过编写附加代码来开发全新的访问方法类型。
每个表访问方法都由系统目录 pg_am 中的一行描述。pg_am 条目指定了该表访问方法的名称以及一个处理器函数。这些条目可以通过CREATE ACCESS METHOD和DROP ACCESS METHOD SQL 命令创建和删除。
表访问方法的处理器函数必须声明为接受一个 internal 类型的参数,并返回伪类型 table_am_handler。这个参数只是一个占位值,用来防止处理器函数被 SQL 命令直接调用。
下面展示扩展 SQL 脚本文件如何创建表访问方法处理器:
CREATE OR REPLACE FUNCTION my_tableam_handler(internal) RETURNS table_am_handler AS 'my_extension', 'my_tableam_handler' LANGUAGE C STRICT; CREATE ACCESS METHOD myam TYPE TABLE HANDLER my_tableam_handler;
该函数的结果必须是一个指向 TableAmRoutine 结构体的指针,其中包含核心代码使用该表访问方法所需的全部信息。返回值需要具有服务器生命周期,这通常通过将其定义为全局作用域中的 static const 变量来实现。
下面是一个包含表访问方法处理器的源文件示例:
#include "postgres.h"
#include "access/tableam.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
static const TableAmRoutine my_tableam_methods = {
.type = T_TableAmRoutine,
/* Methods of TableAmRoutine omitted from example, add them here. */
};
PG_FUNCTION_INFO_V1(my_tableam_handler);
Datum
my_tableam_handler(PG_FUNCTION_ARGS)
{
PG_RETURN_POINTER(&my_tableam_methods);
}
TableAmRoutine 结构体也称为该访问方法的API 结构体,它通过回调来定义访问方法的行为。这些回调是普通 C 函数的指针,在 SQL 层既不可见也不可调用。所有回调及其行为都定义在 TableAmRoutine 结构体中(结构体内的注释说明了对回调的要求)。大多数回调都有包装函数,其文档是从表访问方法使用者而非实现者的角度编写的。详情请参阅 src/include/access/tableam.h 文件。
实现访问方法时,通常需要实现专用的元组表槽位类型(参见 src/include/executor/tuptable.h),使访问方法之外的代码可以持有该方法的元组引用,并访问元组各列。
目前,AM 实际存储数据的方式所受限制相当少。例如,可以使用 postgres 的共享缓冲区缓存,但这并非必需。如果使用它,那么采用 PostgreSQL 在第 66.6 节中描述的标准页面布局通常是有意义的。
表访问方法 API 目前的一项较大限制是:若访问方法希望支持修改操作和/或索引,每个元组必须有一个由块号和项号组成的元组标识符 TID(另见第 66.6 节)。TID 各部分不必具有与 heap 中完全相同的含义;但如果要支持可选的位图扫描,块号就需要提供局部性。
为保证崩溃安全,AM 可以使用 postgres 的WAL,也可以使用自定义实现。如果选择了 WAL,可以使用通用 WAL 记录,也可以实现一个自定义 WAL 资源管理器。
要以允许在单个事务中访问不同表访问方法的方式实现事务支持,很可能需要与 src/backend/access/transam/xlog.c 中的机制紧密集成。
开发新的表访问方法时,可以参照 src/backend/access/heap/heapam_handler.c 中现有的堆实现,了解实现细节。
相关条目
文档与源码
- PostgreSQL 18 English manual
- src/backend/access/heap/heapam_handler.c:2616
- PostgreSQL 18 English manual
- PostgreSQL 18 English manual
- PostgreSQL 18 English manual
- PostgreSQL 18 English manual
来源构建
- 版本
- 18.6
- 构建
- PostgreSQL 18.6 source archive
- 来源指纹
555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f
版本比较
PostgreSQL 12 → 13: 属性变化。
以下差异保留原始字段名与英文源描述。
--- PostgreSQL 12
+++ PostgreSQL 13
@@ -1,7 +1,6 @@
{
"callbacks": {
"compute_xid_horizon_for_tuples": "heap_compute_xid_horizon_for_tuples",
- "finish_bulk_insert": "heapam_finish_bulk_insert",
"index_build_range_scan": "heapam_index_build_range_scan",
"index_fetch_begin": "heapam_index_fetch_begin",
"index_fetch_end": "heapam_index_fetch_end",
@@ -15,10 +14,12 @@
"relation_copy_data": "heapam_relation_copy_data",
"relation_copy_for_cluster": "heapam_relation_copy_for_cluster",
"relation_estimate_size": "heapam_estimate_rel_size",
+ "relation_fetch_toast_slice": "heap_fetch_toast_slice",
"relation_needs_toast_table": "heapam_relation_needs_toast_table",
"relation_nontransactional_truncate": "heapam_relation_nontransactional_truncate",
"relation_set_new_filenode": "heapam_relation_set_new_filenode",
- "relation_size": "heapam_relation_size",
+ "relation_size": "table_block_relation_size",
+ "relation_toast_am": "heapam_relation_toast_am",
"relation_vacuum": "heap_vacuum_rel",
"scan_analyze_next_block": "heapam_scan_analyze_next_block",
"scan_analyze_next_tuple": "heapam_scan_analyze_next_tuple",
比较已记录的接口与属性,排除来源指纹和构建元数据。某个样本中没有记录,不能据此判断实际引入或移除的版本。
导出 JSON · 返回Table AM · 收录范围为 PostgreSQL 12 至 20;最早采样版本不一定是实际引入版本。