Почему запрос с фильтрацией по имени может работать медленно
Что проверяют
Понимаете ли вы, какие условия по строковой колонке индекс обслуживает, а какие нет. Вопрос звучит бытово, но за ним точная механика: обычный индекс упорядочен по значению, и искать по нему можно только слева направо.
Как отвечать
Разберите по видам поиска.
Точное совпадение и поиск по префиксу обычный индекс по B-дереву закрывает: условие вида name LIKE 'ив%' превращается в поиск по диапазону. Но в PostgreSQL есть подвох: при нелатинской локали базы для этого нужен индекс с классом операторов text_pattern_ops, иначе порядок в индексе не совпадает с порядком сравнения и префиксный поиск в него не попадёт.
Поиск подстроки с ведущим подстановочным знаком, то есть name LIKE '%ив%', обычному индексу недоступен в принципе: неизвестно, с чего значение начинается. Здесь нужен триграммный индекс, то есть расширение pg_trgm и GIN по колонке. Для поиска по словам с морфологией берут полнотекстовый индекс по tsvector.
Регистронезависимое сравнение через lower(name) = $1 требует индекса ровно по тому же выражению. Индекс по самой колонке тут не сработает.
Со стороны Go добавьте два пункта: параметры передавать плейсхолдерами, а не склейкой строки, и экранировать подстановочные знаки во вводе пользователя, иначе введённый знак процента превратит поиск в полное сканирование.
Где спотыкаются
Советуют упростить условие и искать по точному совпадению. Это не оптимизация, а отказ от требования: продуктовый поиск по части имени никуда не денется, его нужно закрыть подходящим индексом.
Второе: предлагают распараллелить запрос горутинами. Горутины не ускоряют одну выборку, они лишь добавят одновременных соединений к той же базе и сделают хуже.
Третье: создают индекс, видят прежнее время и решают, что индексы не работают. Обычно индекс просто не подходит условию, и EXPLAIN показывает это сразу: в плане стоит последовательное чтение, а созданный индекс не упоминается вовсе.