Я немного изменил свой запрос (объединенный пробел), чтобы обойти индекс триграммы, и проверил, что медленные запросы возвращаются к индексу btree и время выполнения <10 мс. </p>
Это уродливо, но это почти наверняка решение. Может быть, мы сможем исправить ситуацию, чтобы в какой-то (далекой) будущей версии PostgreSQL такие исправления не потребовались, но сегодня это вам не поможет.
Bitmap Index Scan on trgm_idx (cost=0.00..345.00 rows=667 width=0) (actual time=1325.867..1325.867 rows=5833670 loops=1)
Эта оценка явно ненормальный, и это, вероятно, источник проблемы. Но индексы триграмм и запросы ILIKE очень чувствительны к тексту запроса. Наличие только (очевидно) анонимизированного значения '%some_text%'
недостаточно для более глубокого изучения.
И другой подход будет использовать использование GiST, а не GIN. Индексы GiST могут выгодно использовать несколько столбцов одновременно.
CREATE INDEX CONCURRENTLY IF NOT EXISTS trgm_idx ON table1 USING gist
(some_id, some_timestamp, (COALESCE(field1, '') || ' ' || COALESCE(field2, '') || COALESCE(field3, '') || ' ' || COALESCE(field4, '') || ' ' || COALESCE(field5, '') || ' ' || field6::text) gist_trgm_ops);
Возможно, вы захотите включить только один или другой из первых двух столбцов в зависимости от степени избирательности каждого из них. Возможно, вам придется провести несколько экспериментов.
Мне не нравится использовать GiST с pg_trgm, я считаю, что производительность (как при использовании, так и при сборке) errati c. Но для такого полезного многостолбцового индекса у вас нет другого выбора.
В любом случае, у вас есть индекс, который уже работает хорошо, он просто не использует его. Создание индекса GiST может быть «достаточно хорошим», чтобы отвлечь запрос от GIN, но тогда он может просто заставить какой-то другой запрос выбрать неправильный план.
Другой подход заключается в использовании индексов RUM, это позволяет вам сортировать по данным, хранящимся в индексе, но я думаю, вам придется написать код , чтобы они поддерживали pg_trgm.