12.9. GiST和GIN索引类型

有两种类型的索引可以用于加快全文搜索。注意全文检索不一定非要使用索引。 但是在规则基础上搜索列的情况下,索引往往是可取的。

CREATE INDEX name ON table USING gist(column);

创建以GiST(通用搜索树)为基础的索引,column可以是tsvector or tsquery 类型。

CREATE INDEX name ON table USING gin(column);

创建以GIN(基因倒排索引)为基础的索引,column必须是tsvector类型。

在两个索引类型之间有着巨大的性能差异,因此了解它们的特性是很重要的。

GiST索引是有损耗的,这意味着该索引可能会产生错误的匹配, 并且有必要检查实际的表行消除这种错误匹配(PostgreSQL需要时自动执行)。 GiST索引是有损耗的,因为每个文档在索引中通过一个固定长度的标签进行表示。 它是通过散列每个单词到一个n位的字符串的单一的点产生,所有这些位OR-ed一起产生一个n位的文件标签。 当两个单词散列到相同点的位置,将有一个错误匹配。如果查询中的所有单词匹配(真实的或错误的), 则必须检索表行查看匹配是否是正确的。

数据丢失导致了性能下降,由于表记录的不必要的获取,产生了错误的匹配。 由于随机访问表记录是缓慢的,这限制了GiST索引的效能。错误匹配的可能性取决于几个因素, 特别是独特词的数量,所以推荐使用词典来降低这些数量。

GIN索引并没有损耗标准查询,但它们的性能取决于对数独特的单词数。 (然而,GIN索引只存储tsvector值的字(词),而不是它们的权重标签。因此, 当使用涉及权重的查询时,需要复查一个表行。)

在选择要使用的索引类型时,GiST或者GIN考虑这些性能上的差异:

一般来说,GIN索引对静态数据是最好的,因为查找速度很快。对于动态数据, GiST索引更新比较快。具体而言,GiST索引非常适合动态数据,并且如果独特的字(词)在100,000以下, 则比较快,而GIN索引将处理100,000+词汇,但是更新比较慢。

请注意,GIN索引编译时间通常可以通过增加maintenance_work_mem改进, 而GiST索引编译时间对参数不敏感。

大集合的分区以及GiST和GIN索引的合理使用允许非常快速的搜索与在线升级的实现。 分区可以在数据库级别使用表继承,或者在服务器发布文档并且使用dblink模块采集搜索结果。 后者是可能的,因为相关函数只使用本地信息。