Table of Contents
PostgreSQL 对 SQL 标准中的 TABLESAMPLE 子句提供了强大的扩展支持。除标准强制要求的 BERNOULLI 与 SYSTEM 算法外,允许开发者编写自定义采样方法。采样方法决定了在使用 TABLESAMPLE 子句时将挑选表中的哪些数据行。
在 SQL 层,表采样方法由一个单一的 SQL 函数表示(通常用 C 语言实现),其函数签名如下:
method_name(internal) RETURNS tsm_handler
函数的名称即为在 SQL 中出现在 TABLESAMPLE 子句中的方法名称。类型为 internal 的实参仅用于防止该函数在 SQL 层被直接调用。该函数的返回值必须是一个 palloc 分配的 TsmRoutine 结构体指针,其中包含了采样方法所需的一组 C 语言底层回调支持函数指针。这些支持函数在 SQL 层不可见或直接调用,详见 Section 59.1。
除回调函数指针外,TsmRoutine 结构体还必须提供以下关键控制字段:
List *parameterTypes
这是一个类型 OID 列表,包含了该采样方法在 TABLESAMPLE 子句中所接受的参数类型。例如,对于内置方法,该列表仅包含单一类型为 FLOAT4OID 的项,代表采样百分比。自定义采样方法可以声明更多或不同类型的参数。
bool repeatable_across_queries
若为 true,表明该采样方法在输入参数与 REPEATABLE 随机数种子相同且表内容未变的情况下,在多次独立查询之间能够提供完全相同的样本集合。若为 false,该采样方法将不接受使用 REPEATABLE 子句。
bool repeatable_across_scans
若为 true,表明在同一查询的多次扫描中(假设参数、种子和快照不变),该采样方法能够提供完全一致的样本行。若为 false,优化器将禁止生成需要对采样表执行多次重新扫描的计划(如嵌套循环连接的内侧扫描),以防输出不一致。
结构体 TsmRoutine 声明于头文件 src/include/access/tsmapi.h 中。
官方分发包中内置的采样方法是极佳的参考范例。可查看源码树中的 src/backend/access/tablesample 目录(内置方法)以及 contrib 目录中的扩展插件。