【问题标题】:How to make a fast pg_trgm DESC (descending)?如何制作快速的 pg_trgm DESC(降序)?
【发布时间】:2019-07-04 07:47:52
【问题描述】:

我在一个表中有一个包含 100.000 个句子的列表,使用 pg_trgm 我可以使用 GIN/GIST 非常快速地获得最接近的字符串 "super cool"指数。见官方例子:

https://www.postgresql.org/docs/11/pgtrgm.html

遗憾的是,我想要相反,我想要最不同的第一个,但是DESC时没有使用GIN/GIST索引,所以很慢.

SELECT t, 'super cool' <-> t AS dist
  FROM test_trgm
  ORDER BY dist DESC LIMIT 10;

我怎么能这样做?从源代码重建 pg_trgm ?怎么样?

【问题讨论】:

  • 我相信您可能需要使用 GiST 来索引距离匹配。
  • @Lucas 我都试过了。

标签: postgresql performance indexing pg-trgm


【解决方案1】:

我认为这根本无法优化,除非事先知道“t”或者你可以缓存一些东西。即使您尝试更改 Postgres 源,也很可能根本看不到任何好处。

在文档中, 运算符是相似度(t1, t2) 的简写。如果两个术语都已知,您可以索引这些分数,例如,您可以为任何 t1、t2 组合“创建此函数的索引”,它将起作用。这将是一个标准的 BTree 索引,您可以执行小于、大于或任何您想要的检查或排序。

但是 t2 是未知的,因此,您不能为任何可能的字符串创建索引。 (或者,如果数量合理,您可以在表格中伪造所有可能的字符串组合)

如果您不知道另一个术语,排序是如何工作的?好吧,因为您可以获得单词 t1,提取所有三元组,并获得哪些行(tid)至少出现 X 次。这很快,因为您只需检查原始单词的 N 个三元组,检索桶中的元组 id,计数和排序。

现在试着反过来做:你需要所有没有共同三元组的单词。因此,您必须扫描检索到的三元组,获取元组 id,然后获取整个表,过滤掉您之前获得的元组 id。然后继续那些只有 1 个三元组的,然后是 2 个,依此类推。这听起来效率很低,就像扫描整个表和索引一两次一样。

主要问题在于检索零重合的匹配项。不管怎么做,都需要扫描整个表。

如果您至少可以跳过那些符合率为零的内容,那么您可以加快搜索速度。为此,您可以使用 set_limit(0.0001) 并使用“%”运算符将它们过滤掉。 (但听起来这不是你想要的)

即使将三元组提取到数组或子表中似乎也无济于事。你的问题看起来像一个布隆过滤器,但反过来了,我仍然不确定是否有可能创建这样的索引。

也许如果你添加更多关于你想要完成什么的信息,我们可以找到不使用三元组的不同方法。

【讨论】:

  • 谢谢,我想找到最不同的字符串。它可能是最大的 levenshtein,但速度很快。这在数学上似乎是不可能的。
【解决方案2】:

我想提议

select * 
from ( 
  SELECT  row_number() OVER () as rk, t, 'super cool' <-> t AS dist   
  FROM test_trgm
) sub  
ORDER BY rk DESC LIMIT 10;

【讨论】:

  • 你需要在ROW_NUMBER函数的OVER子句中有ORDER BY
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-21
  • 2016-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多