本章解释了核心 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
文件。
要实现一个访问方法,实现者通常需要实现一个AM特定的元组表槽(tuple table slot)(参见 src/include/executor/tuptable.h
),它允许访问方法外部的代码持有对 AM 元组的引用,并访问元组的列。
目前,AM 实际存储数据的方式相当宽松。例如,可以使用 postgres 的共享缓冲区缓存,但并非强制要求。如果使用,那么使用 PostgreSQL 的标准页面布局(如 第 66.6 节中所述)可能是有意义的。
表访问方法 API 的一个相当大的限制是,目前,如果 AM 希望支持修改和/或索引,那么每个元组必须有一个元组标识符(TID),由块号和项号组成(另请参见 第 66.6 节)。TID 的子部分不一定具有与 heap
相同的含义,但如果需要位图扫描支持(这是可选的),则块号需要提供局部性。TIDs具有与 heap
相同的含义,但如果需要位图扫描支持(它是可选的),则块号需要提供局部性。
为了崩溃安全,AM 可以使用 postgres 的 WAL,或者自定义实现。如果WAL被选中,可以使用 通用 WAL 记录,也可以实现 自定义 WAL 资源管理器。
要以允许在单个事务中访问不同表访问方法的方式实现事务支持,可能需要与 src/backend/access/transam/xlog.c
中的机制紧密集成。
任何新的 table access method
的开发者都可以参考现有 heap
实现(位于 src/backend/access/heap/heapam_handler.c
)以获取其实现的详细信息。
如果您在文档中看到任何不正确、与您对特定功能的体验不符或需要进一步澄清的内容,请使用 此表格 报告文档问题。