PostgreSQL GIN 索引比 pg_trgm 的 GIST 慢?
Posted
技术标签:
【中文标题】PostgreSQL GIN 索引比 pg_trgm 的 GIST 慢?【英文标题】:PostgreSQL GIN index slower than GIST for pg_trgm? 【发布时间】:2017-03-24 20:14:34 【问题描述】:尽管所有文档都这么说,我发现 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 上。
【问题讨论】:
缺少有关性能问题的一些信息。表定义、表和索引的总大小。 See instructions here. 【参考方案1】:有些问题很突出:
首先,考虑升级到当前版本的 Postgres。在撰写本文时,这是 pg 9.6 或 pg 10(当前为测试版)。自 Pg 9.4 以来,对 GIN 索引、附加模块 pg_trgm 和大数据进行了多项改进。
接下来,您需要更多的 RAM,尤其是更高的 work_mem
设置。我可以从EXPLAIN
输出中的这一行看出:
Heap Blocks: exact=7625 lossy=223807
“有损”在 Bitmap Heap Scan 的详细信息中(带有您的特定数字)表示 work_mem
的严重短缺。 Postgres 仅在位图索引扫描中收集块地址而不是行指针,因为使用较低的work_mem
设置(不能在 RAM 中保存确切地址)预计会更快。更多不符合条件的行必须以这种方式在以下位图堆扫描中进行过滤。这个相关的答案有详细信息:
但是不要把work_mem
设置得太高不考虑整体情况:
可能还有其他问题,例如索引或表膨胀或更多配置瓶颈。但是如果你只修复这两个项目,查询应该已经快很多了。
另外,您真的需要检索示例中的所有 40k 行吗?您可能希望在查询中添加一个小的 LIMIT
并使其成为“最近邻”搜索 - 在这种情况下,GiST 索引毕竟是更好的选择,因为 /em> 应该使用 GiST 索引更快。示例:
【讨论】:
非常感谢!机器有足够的内存,所以我会尝试增加 work_mem 设置。最终查询将使用限制,为简单起见,我将其从示例中删除 - 添加它不会更改查询计划(除了明显添加限制)。以上是关于PostgreSQL GIN 索引比 pg_trgm 的 GIST 慢?的主要内容,如果未能解决你的问题,请参考以下文章
PostgreSQL 未对 JSONB 上的 GIN 索引使用索引扫描
PostgreSql jsonb 列上的 GIN 索引未在查询中使用