12.9. 文本搜索的首选索引类型#
有两种索引可用于加速全文搜索:GIN和GiST。请注意,索引对于全文搜索不是必需的,但在定期搜索某一列的情况下,通常需要一个索引。
要创建此类索引,请执行以下操作之一
-
CREATE INDEX
名称
ON表
USING GIN (列
); 创建一个基于 GIN(广义倒排索引)的索引。
列
必须为tsvector
类型。-
CREATE INDEX
名称
ON表
USING GIST (列
[ { DEFAULT | tsvector_ops } (siglen =数字
) ] ); 创建一个基于 GiST(广义搜索树)的索引。
列
可以为tsvector
或tsquery
类型。可选的整数参数siglen
确定签名长度(以字节为单位)(有关详细信息,请参见下文)。
GIN 索引是首选的文本搜索索引类型。作为倒排索引,它们为每个单词(词素)包含一个索引条目,其中包含匹配位置的压缩列表。多单词搜索可以找到第一个匹配项,然后使用索引删除缺少其他单词的行。GIN 索引仅存储tsvector
值的单词(词素),而不存储其权重标签。因此,在使用涉及权重的查询时需要重新检查表行。
GiST 索引是有损的,这意味着索引可能会产生错误匹配,并且有必要检查实际表行以消除此类错误匹配。(PostgreSQL在需要时会自动执行此操作。)GiST 索引有损,因为每个文档在索引中都由固定长度的签名表示。签名长度(以字节为单位)由可选整数参数siglen
的值确定。默认签名长度(当未指定siglen
时)为 124 字节,最大签名长度为 2024 字节。签名是通过将每个单词哈希到 n 位字符串中的单个位来生成的,并将所有这些位进行 OR 运算以生成 n 位文档签名。当两个单词哈希到相同位位置时,将出现错误匹配。如果查询中的所有单词都有匹配项(真实或错误),则必须检索表行以查看匹配项是否正确。较长的签名会导致更精确的搜索(扫描较小部分的索引和更少的堆页),但代价是索引更大。
GiST 索引可以是覆盖索引,即使用INCLUDE
子句。包含的列可以具有没有任何 GiST 运算符类的任何数据类型。包含的属性将以未压缩的形式存储。
由于不必要的表记录获取(结果证明是错误匹配)会导致性能下降,因此会造成信息丢失。由于对表记录的随机访问很慢,因此这限制了 GiST 索引的实用性。错误匹配的可能性取决于多个因素,特别是唯一单词的数量,因此建议使用词典来减少此数量。
请注意,通常可以通过增加maintenance_work_mem来改善GIN索引的构建时间,而GiST索引的构建时间对此参数不敏感。
对大型集合进行分区以及正确使用 GIN 和 GiST 索引允许实现具有在线更新的非常快速的搜索。可以使用表继承在数据库级别进行分区,或者通过在服务器上分发文档并收集外部搜索结果(例如,通过外部数据访问)进行分区。后者之所以可行,是因为排名函数仅使用本地信息。