Я бы поступил так: проанализировал проблему, нашел ее источник и не стал бы усложнять то, что можно упростить. Источник - это произвольный ввод ФИО. Зачем делать для ФИО сплошную строку ввода? А откуда пользователю знать, в каком порядке что вводить? Строку поиска гугла имитируете? А оно точно нужно? Делайте отдельно 3 поля. И будете иметь структуру, которая идеально ложится на 3 колонки. Можно бахнуть составной индекс на них даже. Только не уникальный, а то ФИО так себе уник. Нет, в вашем случае: 1) храним имя, фамилию, отчество, через пробел в БД 2) полученный ввод бьем на слова по пробелу через explode 3) формируем динамически запрос, чтобы там были секции where like %% по количеству слов, полученных со входа 4) за один запрос стреляем в цель Или типа того. Не усложняйте, упрощайте.
@виталий032 рабочий пример поиска по одному полю, с подсветкой и ранжированием. Код (Text): select id, name, ts_headline(name, query, 'StartSel=<em>, StopSel=</em>') as headline, ts_rank(to_tsvector('english', name), query) as rank from datatable, to_tsquery('english', 'PS91:* | ecst:* | x3:*') as query where to_tsvector('english', name) @@ query order by rank desc; Единственная сложность здесь - преобразовать пользовательский ввод в формат tsquery, но в принципе это решается парой замен в пользовательском запросе, синтаксис очень прост. https://postgrespro.ru/docs/postgrespro/10/textsearch-controls По скорости: Таблица небольшая, ~200к записей, запрос выполняется ~700мс, что довольно много конечно. После добавления индекса Код (Text): CREATE INDEX IF NOT EXISTS idx_datatable_vector ON datatable USING gin(to_tsvector('english', name)); Скорость выполнения запроса ~11мс, что приемлемо ) Далее можете покурить setweight, что бы искать сразу по нескольким полям с различными весами для полей, а мои полномочия на этом всё ) p.s. Код (Text): select id, name from data_goods_tyres where name LIKE '%PS91%' OR name LIKE '%ecst%' OR name LIKE '%x3%' выполняется ~40мс с индексом по полю, но без выделения и ранжирования. Итог: я бы лично не заморачивался и остановился на LIKE, при необходимости - переехал на первый вариант. Если его допилить, то на нем спокойно можно будет дожить до нагрузок требующих отдельных решений типа elastic`а.