我在 Postgres 中使用 trigram 相似性来帮助我灵活地搜索数据库中的名称,并且(更重要的是)从自然语言句子中提取名称并将它们与数据库记录匹配。
使用此查询,我得到了第一个可靠地工作并且快速完成的任务:
SELECT *, similarity(name_column, 'name im searching for') AS sim
FROM table_with_names
WHERE name_column % 'name im searching for'
ORDER BY sim DESC
LIMIT 5;
上面的查询使用了name_column
这个语句的索引:
CREATE INDEX name_sim_idx ON table_with_names USING GIN (name_column gin_trgm_ops);
我的其他任务(从完整的句子中灵活地提取名称匹配)让我感到沮丧。似乎包含该函数的pg_trgm 模块similarity()
也有一个word_similarity()
函数,它完全可以做我需要做的事情。事实上,我用这个查询完成了任务:
SELECT *, word_similarity(name_column, 'sentence including the name im searching for') AS sim
FROM table_with_names
WHERE name_column <% 'sentence including the name im searching for'
ORDER BY sim DESC
LIMIT 5;
然而。虽然我列出的第一个查询(相似性查找,而不是提取)非常快(1 毫秒),但第二个查询在 ~350 毫秒时非常慢,并且不会使用我的 index。
我不明白为什么第二个查询不会使用我的 trgm 索引。我曾尝试使用 来抑制 Seq Scan SET enable_seqscan = off;
,但这不起作用。据我所知,Postgres 的文档声称<%
如果您想使用索引来加速word_similarity()
查询,则该运算符是正确的运算符,但他们的所有示例都以相反的方向使用它。
例如,文档显示:
WHERE 'search text' <% column
而我需要做相反的事情:
WHERE column <% 'search text
我想用 trgm 相似性做些什么?或者我在这里旋转我的轮子。我无法想象为什么我的索引不能在这里使用。这对我来说是 0 意义。希望有人能帮我解决这个问题!提前致谢。
编辑:这是 a_horse_with_no_name 建议的执行计划
Limit (cost=10000000538.89..10000000538.90 rows=5 width=114) (actual time=349.292..349.295 rows=0 loops=1)
Buffers: shared hit=407
-> Sort (cost=10000000538.89..10000000538.91 rows=11 width=114) (actual time=349.290..349.292 rows=0 loops=1)
Sort Key: (word_similarity(full_name, 'this is the sentence that contains the name i am trying to extract'::text)) DESC, period_start DESC
Sort Method: quicksort Memory: 25kB
Buffers: shared hit=407
-> Seq Scan on patient_matching_lookup_v1 (cost=10000000000.00..10000000538.70 rows=11 width=114) (actual time=349.280..349.281 rows=0 loops=1)
Filter: (full_name <% 'this is the sentence that contains the name i am trying to extract'::text)
Rows Removed by Filter: 10534
Buffers: shared hit=407
Planning Time: 0.172 ms
Execution Time: 349.335 ms