66.4. Implementation

在内部,GIN 索引包含在键上构造的 B 树索引,其中每个键是一个或多个索引项的元素(例如,数组的成员),并且叶页中的每个 Tuples 都包含指向堆指针的 B 树(“发布树”),或堆指针的简单列表(“发布列表”),当列表小到足以与键值一起放入单个索引 Tuples 时。

从 PostgreSQL 9.1 开始,索引中可以包含空键值。此外,根据extractValue的索引项为 null 或不包含键的索引项中,占位符 null 包含在索引中。这样一来,应该可以找到空项目的搜索。

通过在组合值(列号,键值)上构建单个 B 树来实现多列 GIN 索引。不同列的键值可以具有不同的类型。

66 .4.1. GIN 快速更新技术

由于反向索引的内在本质,更新 GIN 索引的速度往往很慢:插入或更新一个堆行会导致多次插入索引(从索引项中提取的每个键一个)。从 PostgreSQL 8.4 开始,GIN 可以通过将新的 Tuples 插入到临时的,未排序的未决条目列表中来推迟很多工作。在对表进行清理或自动分析时,或者在调用gin_clean_pending_list函数时,或者如果待处理列表变得大于gin_pending_list_limit时,将使用与初始索引创建期间相同的批量插入技术将条目移至主 GIN 数据结构。即使不计算额外的真空开销,这也大大提高了 GIN 索引的更新速度。此外,开销工作可以通过后台处理而不是在前台查询处理中完成。

这种方法的主要缺点是,搜索除了搜索常规索引外还必须扫描未决条目列表,因此,大量未决条目列表将显着降低搜索速度。另一个缺点是,尽管大多数更新速度很快,但导致挂起的列表变得“太大”的更新将导致立即清除周期,因此比其他更新要慢得多。正确使用自动真空可以将这两个问题最小化。

如果一致的响应时间比更新速度更重要,则可以通过关闭 GIN 索引的fastupdate storage 参数来禁用未决条目的使用。有关详情,请参见CREATE INDEX

66 .4.2. 部分匹配算法

GIN 可以支持“部分匹配”查询,在该查询中,查询不能确定一个或多个键的精确匹配,但是可能的匹配在合理的键值范围内(在compare支持方法确定的键排序 Sequences 之内) )。 extractQuery方法不是返回要完全匹配的键值,而是返回作为要搜索范围下限的键值,并将pmatch标志设置为 true。然后使用comparePartial方法扫描键范围。 comparePartial必须为匹配的索引键返回零,对于仍在要搜索范围内的不匹配项,返回小于零;如果索引键超出了可以匹配的范围,则返回大于零。