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 是否与给定范围的索引值一致。要使用的属性编号作为扫描键的一部分传递。这是 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。使用它们的运算符类定义已根据需要为核心数据类型提供。用户可以使用等效定义为其他数据类型定义其他运算符类,而无需编写任何源代码;声明适当的目录条目就足够了。请注意,运算符策略语义的假设已嵌入到支持函数的源代码中。
实现完全不同语义的运算符类也是可能的,前提是编写了上述四个主要支持函数的实现。请注意,不保证主要版本之间的向后兼容性:例如,以后的版本可能需要其他支持函数。
要为实现完全有序集合的数据类型编写运算符类,可以使用 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 | 操作符 does-not-extend-above | 操作符策略 11 |
操作符策略 10 | 操作符 is-below | 操作符策略 12 |
操作符策略 11 | 操作符 is-above | 操作符策略 9 |
操作符策略 12 | 操作符 does-not-extend-below | 操作符策略 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
作为包含的示例。
如果您在文档中看到任何不正确、与您对特定功能的体验不符或需要进一步澄清的内容,请使用 此表单 报告文档问题。