尽管所有文档都说明了,但我发现GIN索引要比pg_trgm相关搜索的GIST索引慢得多。这是一个包含2500万行的表格,文本字段相对较短(平均长度为21个字符)。大多数文本行都是“123 Main st,City”形式的地址。
使用
之类的搜索,GIST索引大约需要4秒select suggestion from search_suggestions where suggestion % 'seattle';
但是当使用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上。
答案 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索引,应该更快。例如: