Skip to content

71.3. 可扩展性#

BRIN接口具有很高的抽象级别,要求访问方法实现者仅实现正在访问的数据类型的语义。BRIN层本身负责并发、日志记录和搜索索引结构。

要使BRIN访问方法正常工作,只需实现一些用户定义的方法,这些方法定义了存储在索引中的摘要值的特性以及它们与扫描键交互的方式。简而言之,BRIN将可扩展性与通用性、代码重用和简洁的界面相结合。

对于BRIN,操作符类必须提供四种方法

BrinOpcInfo *opcInfo(Oid type_oid)

返回有关索引列摘要数据的内部信息。返回值必须指向一个已分配的 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 是否与范围的给定索引值一致。作为扫描键的一部分传递要使用的属性编号。这是与向后兼容的较旧一致函数变体。

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() 宏从其他支持函数访问这些选项。

由于索引值的键提取和 中键的表示都是灵活的,因此它们可能取决于用户指定的参数。

核心发行版包括对四种类型的运算符类的支持:minmax、minmax-multi、inclusion 和 bloom。根据需要,使用它们的操作符类定义会运用于内核数据类型。用户可以使用等效的定义为其他数据类型定义其他运算符类,而无需编写任何源代码;声明适当的目录条目就足够了。请注意,运算符策略语义的假设已嵌入到支持函数的源代码中。

实现完全不同语义的运算符类也是可能的,前提是编写了上面描述的四个主要支持函数的实现。请注意,不保证主要版本之间的向后兼容性:例如,在以后的版本中可能需要其他支持函数。

要为实现完全有序集的数据类型编写运算符类,可以使用 minmax 支持函数以及相应的运算符,如表 71.2所示。所有运算符类成员(函数和运算符)都是必需的。

表 71.2. Minmax 运算符类的函数和支持编号

运算符类成员对象
支持函数 1内部函数 brin_minmax_opcinfo()
支持函数 2内部函数 brin_minmax_add_value()
支持函数 3内部函数 brin_minmax_consistent()
支持函数 4内部函数 brin_minmax_union()
运算符策略 1运算符小于
运算符策略 2运算符小于或等于
运算符策略 3运算符等于
运算符策略 4运算符大于或等于
运算符策略 5运算符大于

要为包含在另一种类型中的值的复杂数据类型编写运算符类,可以使用包含支持函数以及相应的运算符,如表 71.3中所示。它只需要一个附加函数,该函数可以用任何语言编写。可以定义更多函数以获得更多功能。所有运算符都是可选的。某些运算符需要其他运算符,如表中所示的依赖项。

表 71.3. 包含运算符类的函数和支持编号

运算符类成员对象依赖项
支持函数 1内部函数 brin_inclusion_opcinfo()
支持函数 2内部函数 brin_inclusion_add_value()
支持函数 3内部函数 brin_inclusion_consistent()
支持函数 4内部函数 brin_inclusion_union()
支持函数 11合并两个元素的函数
支持函数 12可选函数,用于检查两个元素是否可合并
支持函数 13可选函数,用于检查一个元素是否包含在另一个元素中
支持函数 14可选函数,用于检查一个元素是否为空
运算符策略 1运算符位于左侧运算符策略 4
运算符策略 2运算符不延伸到右侧运算符策略 5
运算符策略 3运算符重叠
运算符策略 4运算符不延伸到左侧运算符策略 1
运算符策略 5运算符位于右侧运算符策略 2
运算符策略 6、18运算符相同或相等运算符策略 7
运算符策略 7、16、24、25运算符包含或相等
运算符策略 8、26、27运算符被包含或相等运算符策略 3
运算符策略 9运算符不延伸到上方运算符策略 11
运算符策略 10运算符位于下方运算符策略 12
运算符策略 11运算符位于上方运算符策略 9
运算符策略 12运算符不延伸到下方运算符策略 10
运算符策略 20运算符小于运算符策略 5
运算符策略 21运算符小于或等于运算符策略 5
运算符策略 22运算符大于运算符策略 1
运算符策略 23运算符大于或等于运算符策略 1

支持功能编号 1 到 10 保留给 BRIN 内部功能,因此 SQL 级别功能从编号 11 开始。支持功能编号 11 是构建索引所需的主要功能。它应接受两个与运算符类相同数据类型参数,并返回它们的并集。如果包含运算符类使用STORAGE参数定义,则它可以存储具有不同数据类型的并集值。并集函数的返回值应与STORAGE数据类型匹配。

提供支持功能编号 12 和 14 以支持内置数据类型的异常。功能编号 12 用于支持不可合并的不同系列的网络地址。功能编号 14 用于支持空范围。功能编号 13 是可选的,但建议使用,它允许在将新值传递给并集函数之前对其进行检查。由于 BRIN 框架可以在并集未更改时对某些操作进行快捷处理,因此使用此功能可以提高索引性能。

要为仅实现相等运算符并支持哈希的数据类型编写运算符类,可以使用布隆支持过程以及相应运算符,如表 71.4所示。所有运算符类成员(过程和运算符)都是必需的。

表 71.4。布隆运算符类的过程和支持编号

运算符类成员对象
支持过程 1内部函数 brin_bloom_opcinfo()
支持过程 2内部函数 brin_bloom_add_value()
支持过程 3内部函数 brin_bloom_consistent()
支持过程 4内部函数 brin_bloom_union()
支持过程 5内部函数 brin_bloom_options()
支持过程 11计算元素哈希的函数
运算符策略 1运算符等于

支持过程编号 1-10 保留给 BRIN 内部函数,因此 SQL 级别函数从编号 11 开始。支持功能编号 11 是构建索引所需的主要功能。它应接受一个与运算符类相同数据类型参数,并返回该值的哈希。

minmax-multi 运算符类也适用于实现完全有序集的数据类型,并且可以看作是 minmax 运算符类的简单扩展。虽然 minmax 运算符类将每个块范围中的值汇总到一个连续区间,但 minmax-multi 允许汇总到多个较小的区间,以更好地处理异常值。可以使用 minmax-multi 支持过程以及相应运算符,如表 71.5所示。所有运算符类成员(过程和运算符)都是必需的。

表 71.5. minmax-multi 运算符类的过程和支持编号

运算符类成员对象
支持过程 1内部函数 brin_minmax_multi_opcinfo()
支持过程 2内部函数 brin_minmax_multi_add_value()
支持过程 3内部函数 brin_minmax_multi_consistent()
支持过程 4内部函数 brin_minmax_multi_union()
支持过程 5内部函数 brin_minmax_multi_options()
支持过程 11计算两个值之间距离(范围的长度)的函数
运算符策略 1运算符小于
运算符策略 2运算符小于或等于
运算符策略 3运算符等于
运算符策略 4运算符大于或等于
运算符策略 5运算符大于

minmax 和包含运算符类都支持跨数据类型的运算符,但依赖关系会变得更复杂。minmax 运算符类要求定义一组完整的运算符,其中两个参数具有相同的数据类型。它允许通过定义额外的运算符集来支持其他数据类型。包含运算符类运算符策略依赖于另一个运算符策略,如表 71.3所示,或与它们自己相同的运算符策略。它们要求使用STORAGE数据类型作为左侧参数,并使用另一个受支持的数据类型作为受支持运算符的右侧参数来定义依赖运算符。请参阅float4_minmax_ops作为 minmax 的示例,并参阅box_inclusion_ops作为包含的示例。