我有一个包含客户数据的表,它有 1200 万多条记录。我想根据几个字段来查询它,例如:first_name、last_name、birth_place。但是数据真的很脏,所以我想要甚至不完全匹配的记录。我为此使用了 unaccent 和 pg_trgm 模块。
我按照这个问题能够在索引中使用 unaccent,因此f_unaccent()
而不是unaccent()
在查询中。
指数:
CREATE INDEX first_name_idx ON customer USING gist(f_unaccent(coalesce(first_name, '')) gist_trgm_ops);
CREATE INDEX last_name_idx ON customer USING gist(f_unaccent(coalesce(last_name, '')) gist_trgm_ops);
CREATE INDEX birthplace_idx ON customer USING gist(f_unaccent(coalesce(birthplace, '')) gist_trgm_ops);
选择:
WITH t AS (
SELECT id, first_name, f_unaccent(coalesce(first_name, '')) <-> unaccent('Oliver') as first_name_distance,
last_name, f_unaccent(coalesce(last_name, '')) <-> unaccent('Twist') as last_name_distance,
birthplace, f_unaccent(coalesce(birthplace, '')) <-> unaccent('London') as birthplace_distance,
FROM customer
),
s AS (
SELECT t.id, t.first_name_distance + t.last_name_distance + t.birthplace_distance as total FROM t
)
select * from t join s on (t.id = s.id);
当我对其运行分析时,它会进行顺序扫描。它不使用索引。我知道第一个选择在整个桌子上运行,所以也许很好。我使用的是<->
,而不是similarity(text, text)
函数,因为我什至想要一些字段相似度为 0 的记录,相似度之和是我关心的。
在真实数据上,这个查询(有 6 个字段,而不是 3 个)大约需要 12 分钟(没有索引,我没有创建它们,因为我在测试数据上看到它们甚至没有被使用......)
我怎样才能使这个查询运行得更快?谢谢