当前位置: 首页 > 面试题库 >

PostgreSQL的GIN索引比pg_trgm的GIST慢吗?

欧阳哲
2023-03-14
问题内容

尽管所有文档都说了什么,但我发现pg_trgm相关搜索的GIN索引要比GIST索引慢得多。该表位于2500万行的表中,该表的文本字段相对较短(平均长度为21个字符)。文本的大多数行都是“
123 Main st,City”格式的地址。

GIST索引大约需要4秒钟的搜索时间,例如

select suggestion from search_suggestions where suggestion % 'seattle';

但是,使用以下命令运行时,GIN需要90秒,并且得到以下结果EXPLAIN ANALYZE

Bitmap Heap Scan on search_suggestions  (cost=330.09..73514.15 rows=25043 width=22) (actual time=671.606..86318.553 rows=40482 loops=1)
  Recheck Cond: ((suggestion)::text % 'seattle'::text)
  Rows Removed by Index Recheck: 23214341
  Heap Blocks: exact=7625 lossy=223807
  ->  Bitmap Index Scan on tri_suggestions_idx  (cost=0.00..323.83 rows=25043 width=0) (actual time=669.841..669.841 rows=1358175 loops=1)
        Index Cond: ((suggestion)::text % 'seattle'::text)
Planning time: 1.420 ms
Execution time: 86327.246 ms

请注意,即使实际上只有40k行匹配,索引也选择了超过一百万行。有什么想法为什么表现这么差吗?这是在PostgreSQL 9.4上。


问题答案:

一些问题很突出:

首先,考虑升级到 Postgres当前版本 。在撰写本文时为pg 9.6或pg 10(当前为beta)。自Pg
9.4起,对GIN索引,附加模块pg_trgm和大数据进行了多次改进。

接下来,您需要更多的 RAM ,尤其是更高的 work_mem 设置。从EXPLAIN输出中的这一行可以看出:

Heap Blocks: exact=7625 lossy=223807

___位图堆扫描_ (带有您的特定编号)的详细信息中的 “有损”
表示严重短缺work_mem。Postgres仅在位图索引扫描中收集块地址,而不是在行指针中收集,因为在work_mem设置较低的情况下,这样做预计会更快(无法在RAM中保存确切的地址)。这样,必须在下面的
位图堆扫描中 过滤更多的不合格行。这个相关的答案有详细信息:

  • 使用位图索引扫描在查询计划中的“凌晨检查条件:”行

但是,在不考虑整体情况的情况下,不要设置work_mem 太高:

  • 使用ORDER BY日期和文本优化简单查询

可能还有其他问题,例如索引或表膨胀或更多配置瓶颈。但是,如果你只是解决这两个项目,查询应该是 快了。

另外,您是否真的需要检索示例中的所有40k行?你可能要一个小添加 LIMIT 到查询,并使其成为“近邻”搜索-
在这种情况下,其主旨在于指数毕竟是更好的选择,因为 应该是与要旨的索引快。例子:

  • 相似度函数的最佳索引


 类似资料:
  • 问题内容: 我有以下构造函数(作为测试): 我有以下查询,可以正常运行: 但我相信执行此操作的正确方法是使用@>运算符。我有以下内容,但它给出了语法错误: 我该怎么写呢? 问题答案: 阅读hstore文档(您的(最后一个查询))并不意味着“当大小大于或等于41时”: 之后,您将无法编写,因为没有这样的操作。使用运算符: 你可以写: 但是,只需要尺寸等于41且质量等于20的这些产品。

  • 我正在实现一个表,该表有一个数据类型为的列,我正在尝试了解使用什么索引更好? GIN还是GiST? 在这里查看postgres文档时,我似乎了解到: > GiST更新和建立索引的速度更快,但不如gin准确。 GIN更新和构建索引的速度较慢,但更准确。 好吧,那么为什么会有人想要一个gist索引字段而不是杜松子酒呢?如果gist会给你错误的结果?这一定有一些优势(外部性能)。 谁能用外行的话解释一下

  • 问题内容: 我想使用Postgres 9.4 在json列上创建一个索引,该索引将在搜索列中的特定键时使用。 例如,我有一个带有json列“ animals”的“农场”表。 animals列具有通用格式的json对象: 我已经尝试了多个索引(分别): 我想运行如下查询: 并让该查询使用索引。 当我运行此查询时: 那么(1)索引就可以了,但是我无法获得任何索引来解决不平等问题。 这样的索引可能吗?

  • 索引是加速搜索引擎检索数据的一种特殊表查询。简单地说,索引是一个指向表中数据的指针。一个数据库中的索引与一本书的索引目录是非常相似的。 拿汉语字典的目录页(索引)打比方,我们可以按拼音、笔画、偏旁部首等排序的目录(索引)快速查找到需要的字。 索引有助于加快 SELECT 查询和 WHERE 子句,但它会减慢使用 UPDATE 和 INSERT 语句时的数据输入。索引可以创建或删除,但不会影响数据。

  • 问题内容: 我正在建立Django网站,并且正在寻找搜索引擎。 一些候选人: Lucene / Lucene与指南针/ Solr 狮身人面像 PostgreSQL内置全文本搜索 MySQl内置全文本搜索 选择标准: 结果相关性和排名 搜索和索引速度 易于使用,易于与Django集成 资源需求-网站将托管在VPS上,因此理想情况下,搜索引擎不需要大量的RAM和CPU 可扩展性 其他功能,例如“您的意

  • 表字段:id,content(text类型),content字段已添加fulltext索引,10万条数据,内容是用navicat生成的随机文本。 查询SQL如下: 第一条SQL:耗时13秒 第二条SQL:耗时189秒 我搞不懂为啥差距这么大,那fulltext索引的意义在哪里?