Получение LIKE запросов на использование индекса для выражений citext - PullRequest
1 голос
/ 19 сентября 2019

Справочная информация: - Postgres 11.4 на RDS, 11.5 на macOS дома.- В моей тестовой настройке таблица record_changes_log_detail имеет размер около 8 млн.- Поле old_value имеет тип citext.- Значения в поле имеют длину от 1 символа до более 5000.Большинство из них короткие.

Насколько я понимаю, мне нужно использовать здесь индекс выражения, так как некоторые из моих значений слишком длинные для записи B-дерева.В соответствии с примечаниями к выпуску Postgres 11:

«Разрешить создание индексов, которые могут использоваться сравнениями LIKE для столбцов citext (Алексей Чернышов). Для этого индекс должен быть создан с использованием класса операторов citext_pattern_ops."

https://www.postgresql.org/docs/11/release-11.html

Вот такое определение индекса для моих выборочных данных:

CREATE INDEX record_changes_log_detail_old_value_ix_btree
    ON record_changes_log_detail 
    USING btree ((substring(old_value,1,1024)::citext) citext_pattern_ops);

Если я выполню этот анализ запроса, я вижу, что индекс используется:

set max_parallel_workers_per_gather = 0; -- Don't tempt the planner to run a sequential scan.
explain analyze
select * from record_changes_log_detail where substring(old_value,1,1024)::citext = 'Gold Kerrison Neuro';

Итак, поиск = работает так, как ожидалось.Однако этот запрос не использует индекс:

select * from record_changes_log_detail where substring(old_value,1,1024)::citext LIKE 'Gold Kerrison Neuro%';

Есть ли хитрость для получения индексов citext для работы с пропущенными запросами LIKE, или это более вероятноошибка?Для сравнения, запрос LIKE использует индекс, если вы строите его с помощью text_pattern_ops.Но тогда, конечно, он чувствителен к регистру.

1 Ответ

1 голос
/ 19 сентября 2019

Я отправил сообщение в список рассылки об ошибках PG на эту тему и получил ответ от Тома Лейна.Мое резюме ответа "это ошибка документации".Citext_pattern_ops не поддерживает запросы LIKE.

Я решил опубликовать информацию здесь ради архивов.

И, следуя предложению Лоренца Альбе, я попробовал реализовать триграмм Postgres.Они правят!

DROP INDEX IF EXISTS record_changes_log_detail_old_value_ix_tgrm;
CREATE INDEX record_changes_log_detail_old_value_ix_tgrm
    ON record_changes_log_detail 
    USING gin (old_value gin_trgm_ops);

Секрет здесь, когда вы используете citext, заключается в приведении вашего значения к :: text, например так:

select * from record_changes_log_detail 
where old_value::text LIKE '%Gold Kerrison Neuro%';

Запустите это с объяснением анализ для подтверждениячто индекс используется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...