带有unaccent和pg_trgm的多列索引(匹配脏数据)

时间:2018-03-20 15:14:51

标签: postgresql indexing trigram unaccent

我有一个包含客户数据的表,它有12M +记录。我想基于几个字段来查询它,例如:first_name,last_name,birth_place。但是数据真的很脏,所以我想要甚至不完全匹配的记录。我正在使用模块unaccent和pg_trgm。

我遵循此question以便能够在索引中使用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相似性的字段的记录,相似性的SUM是我关心的。

在真实数据上,这个查询(在6个字段中,而不是3个)需要大约12分钟(没有索引,我没有创建它们,因为我在测试数据上看到它们甚至没用过......)< / p>

如何让此查询运行得更快?谢谢

1 个答案:

答案 0 :(得分:1)

由于查询从customer获取所有行,因此使用顺序扫描是最快的选择。