我一直在尝试使用 tsvector 索引进行全文搜索,并发现在 tsvector 类型的列中生成存储向量是一种常见的做法。我们使用的是 Postgres 11.4,但我已经看到这种做法被用作 PG 12 生成列的示例。(比为相同目的使用触发器更简单。)
我的问题是,有什么好处?我在文本字段的 tsvector 上尝试了表达式 GIN 索引,并在存储的 tsvector 上尝试了 GIN 索引。本地大约有 800 万行,我无法测量任何有意义的速度差异。鉴于将向量存储为列和索引需要更多空间,我很好奇是否存在明显的额外成本合理的情况。例如,当您拥有更多角色时。
注意:我们将文本存储在数据库中,因此这不是您在不将源文本吸收到数据库中的情况下索引外部页面/文档/等的设置之一。
如果您使用邻近搜索(例如“phraseto_tsquery”),使用功能索引,它必须将每个匹配候选文档重新解析为 tsvector 并检查它的正确顺序和单词间距。这可能会很慢,尤其是当候选人的数量远高于最终结果的数量时。如果存储了 tsvector,它可以只读取它而不重新解析文档,这要快得多。我认为“ts_headline”等其他高级功能可能处于相同的情况——但我还没有测试过它们。
即使你只是使用“@@”,
我认为如果结果数量的位图不适合“work_mem”,那么它也需要重新解析文档以重新检查“溢出”的候选匹配块. 当然,在这种情况下,增加“work_mem”可能是比添加列更好的选择。值得一提的是,如果您使用RUM而不是 GIN,它将解决函数索引上的 phraseto_tsquery 问题。
有趣的是,我在一个列上创建了一个 GIN 索引,具有一些较大的值(进行文档文本提取,因此如果每行文本页数不多,则为多个段落)。
查询需要 60+s,具体取决于查询,移动到预先计算的向量列 + 索引显着改善了这些查询,“坏查询”下降到 2-3s。
基本上我只是按照https://www.postgresql.org/docs/14/textsearch-tables.html“12.2.2。创建索引”的步骤,从功能索引开始,然后在最后过渡到“列+索引”设置。
所以我强烈推荐任何提出这个问题的人对他们的设置进行基准测试。