Многостолбцовый индекс с unaccent и pg_trgm (соответствует грязным данным)
У меня есть таблица с данными клиентов, в ней более 12 миллионов записей. Я хочу запросить его на основе нескольких полей, например: 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 минут (без индексов я их не создавал, потому что видел в тестовых данных, что они даже не используются...)
Как я могу сделать этот запрос быстрее? Спасибо
1 ответ
Поскольку запрос выбирает все строки из customer
Использование последовательного сканирования является самым быстрым вариантом.