56.3. 实现

本节讨论实现细节和其他对SP-GiST操作符类的实现者有用的技巧。

56.3.1. SP-GiST的限制

单个的叶元组和内部元组必须容纳在一个索引页(默认8KB)里。 因此,当索引可变长数据类型的值时,长值只能被像基数树这样的方法支持,在树的每一层包含一个前缀,这个前缀足够短,可容纳在一个页面上,并且最后的叶子层级包括的后缀也足够短以容纳在一个页面上。 操作符类只有准备好了处理这样的事情,才应该设置longValuesOK为TRUE。 否则,SP-GiST核心将拒绝一个太大以致不能装入一个页面的数据值的索引请求。

同样,不要让内部元组增长得过大以致不能容纳在一个索引页面,这也是操作符类的责任;这限制了在一个内部元组里可以使用的子节点的数量,以及一个前缀值的最大大小。

另一个限制是,当一个内部元组的节点指向一组叶元组,这些元组必须都在相同的索引页面上。 (这个设计决定是为了减少寻址以及节省把这些元组联接在一起的链接的空间)。 如果叶元组的集合增大到超过一个页面,就会执行分裂并插入一个中间的内部元组。 为了解决这个问题,新内部元组必须把叶子中的值的集合划分到多个节点组。 如果操作符类的picksplit函数未能这样做,SP-GiST 将会采取Section 56.3.3中描述的非常手段。

56.3.2. 没有节点标签的SP-GiST

一些树算法在每个内部元组中使用固定数量的节点; 例如,在四叉树中总是正好的有4个节点,它们代表围绕内部元组的中心点的四个象限。 在这种情况下代码典型的通过数值和节点打交道,没有必要有显式的节点标签。 为了废止节点标签(从而节省一些空间),picksplit函数可以为nodeLabels数组返回NULL。 结果这将导致随后调用chooseinner_consistent函数时,nodeLabels为NULL。 原则上,节点标签可用于一些内部元组,而在相同索引的其它元组上省略。

当使用一个包含无标签节点的内部元组时,choose函数返回spgAddNode是错误的, 因为在这种情况下,节点的集合被假定为固定的。 同样也没有在spgSplitTuple动作中产生无标签节点的条款,因为预计将需要一个spgAddNode动作。

56.3.3. "All-the-same"内部元组

如果操作符类的picksplit函数不能把提供的叶子值划分到至少两个分类中, SP-GiST核心可以覆盖picksplit函数的结果。 如果发生了这种事情,包含多个节点的新的内部元组会被创建。 每个节点的标签都和picksplit给一个节点使用的标签相同(如果有的话),并且叶值被随机划分到这些等价节点中。 allTheSame标志会被设置到这个内部元组上,以警告chooseinner_consistent函数这个元组可能没有它们期望的节点集合。

当处理一个allTheSame元组,choose的结果spgMatchNode 被解释为新的值可以被分配到任何等价节点;核心代码将忽略提供的nodeN值并随机的进入其中一个节点(以保持树的平衡)。 choose返回spgAddNode是错误的,因为将使这些节点不再是所有都等价。 如果要插入的值不匹配现有的节点,必须使用spgSplitTuple动作。

当处理一个allTheSame元组,inner_consistent函数应该返回所有或没有一个节点作为继续索引搜索的目标,因为他们都是等价的。 这可能需要也可能不需要任何特殊的代码,这取决于inner_consistent函数通常假设了多少节点的含义。