对于pg_trgm,PostgreSQL GIN索引比GIST慢吗?

时间:2017-03-24 20:14:34

标签: sql postgresql indexing pattern-matching postgresql-performance

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

使用

之类的搜索,GIST索引大约需要4秒
select suggestion from search_suggestions where suggestion % 'seattle';

但是当使用EXPLAIN ANALYZE

运行时,GIN需要90秒,结果如下
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上。

1 个答案:

答案 0 :(得分:1)

有些问题很突出:

首先,考虑升级到当前版本的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 设置为

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

另外,您真的需要检索示例中的所有40k行吗?您可能希望在查询中添加一个小的 LIMIT 并使其成为“最近邻居”搜索 - 在这种情况下,GiST索引毕竟是更好的选择,因为使用GiST索引,应该更快。例如: