带有多列的Postgres全文搜索,为什么在索引中而不是在运行时连接?


10

在过去的几天里,我在postgres中遇到了全文搜索,并且在跨多列搜索时对索引有些困惑。

postgres 文档讨论了如何ts_vector在串联列上创建索引,如下所示:

CREATE INDEX pgweb_idx ON pgweb 
    USING gin(to_tsvector('english', title || ' ' || body));

我可以这样搜索:

... WHERE 
      (to_tsvector('english', title||' '||body) @@ to_tsquery('english', 'foo'))

但是,如果我想有时仅搜索标题,有时仅搜索正文,有时两者都搜索,则需要3个单独的索引。如果我在第三列中添加了索引,则可能是6个索引,依此类推。

我在文档中没有看到的另一种方法是只是分别索引两列,然后使用普通WHERE...OR查询:

... WHERE
      (to_tsvector('english', title) @@ to_tsquery('english','foo'))
    OR
      (to_tsvector('english', body) @@ to_tsquery('english','foo'))

在大约一百万行中对这两个基准进行基准测试似乎在性能上基本没有区别。

所以我的问题是:

为什么我要连接这样的索引,而不是单独索引列?两者的优点/缺点是什么?

我最好的猜测是,如果我事先知道,我只想搜索两个列(一次不搜索),那么我只需要通过串联使用较少内存的一个索引。


尽管我愿意接受更正,但我不确定如何将串联titlebody索引然后再给出很多价值。我可能只会坚持单独索引它们。另外,如果一次过古怪地以某种方式要求您进行连接,那么我想您可以临时运行查询。
swasheck 2012年

你的猜测是正确的。如果没有其他人这样做,我鼓励您进行自我回答,这里是危险的风格。
jcolebrand

Answers:


3

不,您不需要单独的索引。使用权重功能。它们只是您可以查询的标签。您最多可以有四个标签可查询(AD)。

--search any "field" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick'::tsquery; --true

--search B "field" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick:B'::tsquery; --false

--search B or C "fields" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick:BC'::tsquery; --true

您可能希望串联tsvector,以便可以分别将权重应用于它们,然后将它们放在一起:

select
  setweight( name_column::tsvector, 'A') || setweight( phone_column::tsvector, 'B');

2

实际上,替代方法是在OR中使用where ,而不是AND

如果您在tsvector(body + title)上有索引,并且正在其中搜索,则搜索到的单词可以在title body中。

另外-测试时,请确保表格中的行数合理。

最简单的情况应该显示出很大的区别:找到两个单词-其中一个很可能是标题。另一个-很可能在体内。但是请确保没有太多符合这两个条件的行。例如,您体内可能有30%的单词“ depesz”。您也有〜30%的机会在标题中包含“ mysql”。但是在同一行的任何字段中都没有“ depesz和mysql”的可能性很小。然后使用此类索引检查性能。


哈,好地方,关于OR与AND,我将更新问题。我做到了100万行-不用再等待插入了:)
latentflip 2012年

1
感谢您感谢depesz-这些天我们收到了很多postgres问题,所以我希望您能
留在这里

@杰克:不知道我会-我发现stackexchange网站越来越少用。我通常会尝试获取RSS,但是在stackexchange网站上rss几乎是无用的-这么多旧问题带来的污染。

我在这里为您创建了一个RSS提要-您愿意尝试一下吗?我很乐意努力过滤掉您可能不感兴趣的内容,以获得机会让您更多地参与该网站:-)
杰克说,请尝试topanswers.xyz 2012年

杰克:)我会咬-订阅。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.