unaccent 和 pg_trgm 的多列索引(匹配脏数据)
Multi-column index with unaccent and pg_trgm (matching dirty data)
我有一个带有客户数据的 table,它有超过 1200 万条记录。我想根据几个字段查询它,例如:first_name、last_name、birth_place。但是数据真的很脏,所以我什至想要不完全匹配的记录。为此,我正在使用模块 unaccent 和 pg_trgm。
我遵循这个 question 以便能够在索引中使用无重音符号,因此 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);
SELECT:
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);
当我运行分析它时,它进行顺序扫描。它不使用索引。我知道第一个 select 运行 整个 table,所以也许它很好。我使用的是 <->
,而不是 similarity(text, text)
函数,因为我什至想要一些相似度为 0 的字段的记录,相似度的总和是我关心的。
在真实数据上这个查询(有 6 个字段,而不是 3 个)大约需要 12 分钟(没有索引,我没有创建它们,因为我在测试数据上看到它们甚至没有被使用...... )
如何使此查询 运行 更快?谢谢
由于查询从 customer
中获取 所有 行,使用顺序扫描是最快的选择。
我有一个带有客户数据的 table,它有超过 1200 万条记录。我想根据几个字段查询它,例如:first_name、last_name、birth_place。但是数据真的很脏,所以我什至想要不完全匹配的记录。为此,我正在使用模块 unaccent 和 pg_trgm。
我遵循这个 question 以便能够在索引中使用无重音符号,因此 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);
SELECT:
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);
当我运行分析它时,它进行顺序扫描。它不使用索引。我知道第一个 select 运行 整个 table,所以也许它很好。我使用的是 <->
,而不是 similarity(text, text)
函数,因为我什至想要一些相似度为 0 的字段的记录,相似度的总和是我关心的。
在真实数据上这个查询(有 6 个字段,而不是 3 个)大约需要 12 分钟(没有索引,我没有创建它们,因为我在测试数据上看到它们甚至没有被使用...... )
如何使此查询 运行 更快?谢谢
由于查询从 customer
中获取 所有 行,使用顺序扫描是最快的选择。