63.4. Implementation

本节介绍了实现细节和其他技巧,这些技巧对 SP-GiST 操作符类的实现者有用。

63 .4.1. SP-GiST 限制

单个叶子 Tuples 和内部 Tuples 必须适合单个索引页(默认为 8kB)。因此,当对可变长度数据类型的值构建索引时,长值只能由诸如基数树之类的方法支持,其中基数树的每个级别都包含一个足够短以适合页面的前缀,以及最终叶级别包含一个后缀,该后缀也足够短以适合页面。仅当准备将操作符类安排为发生这种情况时,才应将longValuesOK设置为 TRUE。否则,SP-GiST 内核将拒绝任何对索引值太大而无法容纳在索引页上的请求。

同样,操作员类的责任是内部 Tuples 不要变得太大而无法容纳在索引页上。这限制了一个内部 Tuples 中可以使用的子节点的数量以及前缀值的最大大小。

另一个限制是,当内部 Tuples 的节点指向一组叶 Tuples 时,这些 Tuples 必须全部在同一索引页中。 (这是一个设计决策,旨在减少查找并节省将此类 Tuples 链接在一起的链接中的空间.)如果叶 Tuples 的集合对于页面而言太大,则会执行拆分并插入中间的内部 Tuples。为了解决这个问题,新的内部 Tuples“必须”将一组叶子值划分为多个节点组。如果操作员类的picksplit函数无法执行此操作,则 SP-GiST 核心将采取Section 63.4.3中描述的特殊措施。

63 .4.2. 没有节点标签的 SP-GiST

一些树算法为每个内部 Tuples 使用一组固定的节点;例如,在四叉树中,总是有四个节点与内部 Tuples 的质心点周围的四个象限相对应。在这种情况下,代码通常按编号与节点一起使用,并且不需要显式的节点标签。为了抑制节点标签(从而节省一些空间),picksplit函数可以为nodeLabels数组返回 NULL,同样,choose函数可以在spgSplitTuple动作期间为prefixNodeLabels数组返回 NULL。反过来,这将导致在随后的chooseinner_consistent调用期间nodeLabels为 NULL。原则上,节点标签可以用于某些内部 Tuples,而对于同一索引中的其他内部 Tuples 则可以省略。

当使用具有未标记节点的内部 Tuples 时,choose返回spgAddNode是错误的,因为在这种情况下节点集应该是固定的。

63 .4.3. “所有相同”内部 Tuples

picksplit未能将提供的叶值划分为至少两个节点类别时,SP-GiST 核心可以覆盖操作符类的picksplit函数的结果。发生这种情况时,将使用多个节点创建新的内部 Tuples,每个节点都具有picksplit赋予它确实使用过的一个节点的相同标签(如果有),并且叶值在这些等效节点之间随机分配。在内部 Tuples 上设置allTheSame标志,以警告chooseinner_consistent函数该 Tuples 没有他们可能期望的节点集。

当处理allTheSameTuples 时,spgMatchNodechoose结果被解释为意味着可以将新值分配给任何等效节点;核心代码将忽略提供的nodeN值,并随机下降到其中一个节点中(以保持树的平衡)。 choose返回spgAddNode是错误的,因为这会使节点不完全相等。如果要插入的值与现有节点不匹配,则必须使用spgSplitTuple操作。

处理allTheSameTuples 时,inner_consistent函数应返回所有节点或不返回任何节点作为 continue 进行索引搜索的目标,因为它们都是等效的。这可能需要也可能不需要任何特殊情况的代码,具体取决于inner_consistent函数通常假定的节点含义。