Postgresql 中文操作指南
71.3. Extensibility #
BRIN 接口具有很高的抽象级别,只需求访问方法实现者仅实现正在访问的数据类型的语义。BRIN 层本身负责并发性、日志记录和搜索索引结构。
建立一个 BRIN 访问方法所需要的全部是实现一些用户定义的方法,这些方法定义了存储在索引中的摘要值的行为以及它们与扫描键交互的方式。简而言之,BRIN 将可扩展性与通用性、代码重用性和一个干净的接口结合起来。
BRIN 的操作符类必须提供四种方法:
-
BrinOpcInfo *opcInfo(Oid type_oid)
-
返回有关索引列摘要数据的内部信息。返回值必须指向已 palloc 的 BrinOpcInfo ,其定义如下:
-
typedef struct BrinOpcInfo
{
/* Number of columns stored in an index column of this opclass */
uint16 oi_nstored;
/* Opaque pointer for the opclass' private use */
void *oi_opaque;
/* Type cache entries of the stored columns */
TypeCacheEntry *oi_typcache[FLEXIBLE_ARRAY_MEMBER];
} BrinOpcInfo;
-
BrinOpcInfo.oi_opaque 可用于操作符类例程在索引扫描期间在支持函数之间传递信息。
-
bool consistent(BrinDesc *bdesc, BrinValues *column, ScanKey *keys, int nkeys)
-
-
返回所有 ScanKey 条目是否与范围内给定的索引值一致。属性编号将在扫描键的一部分中传递。可以同时传递同一属性的多个扫描键;条目数量由 nkeys 参数确定。
-
bool consistent(BrinDesc *bdesc, BrinValues *column, ScanKey key)
-
-
返回给定范围的 ScanKey 是否与给定的索引值一致。要使用的属性编号作为扫描键的一部分传递。这是与向后兼容更老版本的 consistent 函数的变量。
-
bool addValue(BrinDesc *bdesc, BrinValues *column, Datum newval, bool isnull)
-
-
给定一个索引元组和一个索引值,修改元组的指示属性,以便它再表示新值。如果对元组进行任何修改,将返回 true。
-
bool unionTuples(BrinDesc *bdesc, BrinValues *a, BrinValues *b)
-
-
合并两个索引元组。给定两个索引元组,修改第一个元组的指示属性,以便它表示两个元组。第二个元组未被修改。
BRIN 的操作符类可以(选择)指定以下方法:
-
void options(local_relopts *relopts)
-
定义一组用户可见的参数来控制运算符类的行为。
-
options 函数会传递一个指向 local_relopts 结构的指针,该结构需要填充一组特定于运算符类的选项。可以使用 PG_HAS_OPCLASS_OPTIONS() 和 PG_GET_OPCLASS_OPTIONS() 宏从其他支持函数访问这些选项。
-
由于索引值的关键提取和在 BRIN 中的密钥表示是灵活的,因此它们可能依赖于用户指定的参数。
-
核心发行版支持四种类型的操作符类:minmax、minmax-multi、inclusion 和 bloom。使用它们的算术子类定义根据需要附带用于核心数据类型。用户可以使用等效定义为其他数据类型定义其他操作符类,而无需编写任何源代码;申报适当的目录条目就足够了。请注意,有关操作符策略语义的假设已嵌入在支持函数的源代码中。
也可能实现完全不同语义的操作符类,条件是编写了上面描述的四个主要支持函数的实现。请注意,跨主要发行版向后兼容性不受保证:例如,在以后的版本中可能需要其他支持函数。
要为实现完全有序集的数据类型编写操作员类,可以在 Table 71.2 中所示的方式将 minmax 支持函数与相应操作员一起使用。所有操作员类成员(函数和操作员)都是必需的。
Table 71.2. Function and Support Numbers for Minmax Operator Classes
Operator class member |
Object |
Support Function 1 |
internal function brin_minmax_opcinfo() |
Support Function 2 |
internal function brin_minmax_add_value() |
Support Function 3 |
internal function brin_minmax_consistent() |
Support Function 4 |
internal function brin_minmax_union() |
Operator Strategy 1 |
operator less-than |
Operator Strategy 2 |
operator less-than-or-equal-to |
Operator Strategy 3 |
operator equal-to |
Operator Strategy 4 |
operator greater-than-or-equal-to |
Operator Strategy 5 |
operator greater-than |
要为包含在另一个类型中的值的复杂数据类型编写操作员类,可以在 Table 71.3 中所示的方式将包含支持函数与相应操作员一起使用。它只需要一个附加函数,可以使用任何语言编写。可以定义更多函数以获得其他功能。所有操作员都是可选的。某些操作员需要其他操作员,如表中的依赖项所示。
Table 71.3. Function and Support Numbers for Inclusion Operator Classes
Operator class member |
Object |
Dependency |
Support Function 1 |
internal function brin_inclusion_opcinfo() |
|
Support Function 2 |
internal function brin_inclusion_add_value() |
|
Support Function 3 |
internal function brin_inclusion_consistent() |
|
Support Function 4 |
internal function brin_inclusion_union() |
|
Support Function 11 |
用于合并两个元素的函数 |
|
Support Function 12 |
用于检查两个元素是否可合并的可选函数 |
|
Support Function 13 |
用于检查一个元素是否包含在另一个元素中的可选函数 |
|
Support Function 14 |
用于检查一个元素是否为空的可选函数 |
|
Operator Strategy 1 |
operator left-of |
Operator Strategy 4 |
Operator Strategy 2 |
operator does-not-extend-to-the-right-of |
Operator Strategy 5 |
Operator Strategy 3 |
operator overlaps |
|
Operator Strategy 4 |
operator does-not-extend-to-the-left-of |
Operator Strategy 1 |
Operator Strategy 5 |
operator right-of |
Operator Strategy 2 |
Operator Strategy 6, 18 |
operator same-as-or-equal-to |
Operator Strategy 7 |
运营策略 7、16、24、25 |
operator contains-or-equal-to |
|
运营策略 8、26、27 |
operator is-contained-by-or-equal-to |
Operator Strategy 3 |
Operator Strategy 9 |
operator does-not-extend-above |
Operator Strategy 11 |
Operator Strategy 10 |
operator is-below |
Operator Strategy 12 |
Operator Strategy 11 |
operator is-above |
Operator Strategy 9 |
Operator Strategy 12 |
operator does-not-extend-below |
Operator Strategy 10 |
Operator Strategy 20 |
operator less-than |
Operator Strategy 5 |
Operator Strategy 21 |
operator less-than-or-equal-to |
Operator Strategy 5 |
Operator Strategy 22 |
operator greater-than |
Operator Strategy 1 |
Operator Strategy 23 |
operator greater-than-or-equal-to |
Operator Strategy 1 |
支持函数编号 1 到 10 保留给 BRIN 内部函数,因此 SQL 级别的函数从编号 11 开始。支持函数编号 11 是构建索引所需的主要函数。它应接受两个与操作符类相同数据类型参数,并返回它们的并集。如果 inclusion 操作符类是用 @{6} 参数定义的,则它可以存储有不同数据类型的并集值。并集函数的返回值应与 @{7} 数据类型匹配。
支持函数编号 12 和 14 用于支持内置数据类型的非常规性。函数编号 12 用于支持不可合并的不同类的网络地址。函数编号 14 用于支持空范围。函数编号 13 是可选的,但推荐的,它允许在将新值传递给并集函数之前对其进行检查。由于 BRIN 框架可以在并集未更改时对某些操作进行短路,因此使用这个函数可以提高索引性能。
要为仅实现等式操作符并支持哈希的数据类型编写操作员类,可以在 Table 71.4 中所示的方式将 bloom 支持过程与相应操作员一起使用。所有操作员类成员(过程和操作员)都是必需的。
Table 71.4. Procedure and Support Numbers for Bloom Operator Classes
Operator class member |
Object |
Support Procedure 1 |
internal function brin_bloom_opcinfo() |
Support Procedure 2 |
internal function brin_bloom_add_value() |
Support Procedure 3 |
internal function brin_bloom_consistent() |
Support Procedure 4 |
internal function brin_bloom_union() |
Support Procedure 5 |
internal function brin_bloom_options() |
Support Procedure 11 |
计算元素哈希的函数 |
Operator Strategy 1 |
operator equal-to |
过程支持编号 1-10 保留给 BRIN 内部函数,因此 SQL 级别的函数从编号 11 开始。支持函数编号 11 是构建索引所需的主要函数。它应接受与操作符类相同数据类型的一个参数,并返回该值的哈希值。
minmax-multi 操作符类也适用于实现完全有序集的数据类型,并且可以被视为 minmax 操作符类的简单扩展。虽然 minmax 操作符类将每个块范围的值归纳为一个连续区间,但 minmax-multi 允许归纳为多个较小的区间,以改善处理异常值。可以在 Table 71.5 中所示的方式将 minmax-multi 支持过程与相应操作员一起使用。所有操作员类成员(过程和操作员)都是必需的。
Table 71.5. Procedure and Support Numbers for minmax-multi Operator Classes
Operator class member |
Object |
Support Procedure 1 |
internal function brin_minmax_multi_opcinfo() |
Support Procedure 2 |
internal function brin_minmax_multi_add_value() |
Support Procedure 3 |
internal function brin_minmax_multi_consistent() |
Support Procedure 4 |
internal function brin_minmax_multi_union() |
Support Procedure 5 |
internal function brin_minmax_multi_options() |
Support Procedure 11 |
计算两个值之间距离的函数(范围长度) |
Operator Strategy 1 |
operator less-than |
Operator Strategy 2 |
operator less-than-or-equal-to |
Operator Strategy 3 |
operator equal-to |
Operator Strategy 4 |
operator greater-than-or-equal-to |
Operator Strategy 5 |
operator greater-than |
minmax 和包含操作员类都支持跨数据类型操作符,但使用这些操作符时,依赖关系会变得更加复杂。minmax 操作符类要求定义一组完整的操作符,其两个参数具有相同的数据类型。它允许通过定义额外的操作符集来支持其他数据类型。包含操作员类操作符策略依赖于另一个操作员策略(如 Table 71.3 中所示),或依赖于它们自己的相同操作员策略。它们要求将依赖操作符定义为使用 STORAGE 数据类型作为左手边的参数,并将另一个受支持的数据类型作为受支持操作符的右手边的参数。参见 float4_minmax_ops 中的 minmax 示例和 box_inclusion_ops 中的包含示例。