Ваше 2-е решение выглядит более простым для оптимизации планировщиком, но не исключено, что первое решение получит тот же план.
Для Где, не нужно, поскольку оно покрыто; БД может сделать 2 проверки вместо одной.
Но самая большая проблема - третья, так как она не может быть оптимизирована с помощью индекса.
Так или иначе, PostgreSQL будет сканировать вашу полную таблицу и вручную извлечь совпадения. Это будет медленно для 20 000 или более строк.
Я рекомендую вам изучить нечеткие совпадения строк и полнотекстовый поиск; похоже, это то, что вы пытаетесь подражать.
Даже если вы не хотите использовать полную мощность FTS или нечеткое сопоставление строк, вам определенно следует добавить расширение «pgtrgm», так как оно позволит вам добавить индекс GIN для столбца, который ускорит LIKE '% word 'поиски.
https://www.postgresql.org/docs/current/pgtrgm.html
А если серьезно, взгляните на FTS. Это обеспечивает рейтинг. Если ваши требования строго соответствуют описанным вами, вы все равно можете выполнить запрос FTS к «предварительному фильтру», а затем применить эту логику.
В PostgreSQL FTS есть множество вводных статей, вот одна из них:
https://www.compose.com/articles/mastering-postgresql-tools-full-text-search-and-phrase-search/
И даже недавно я написал сообщение, добавив поиск FTS на свой сайт:
https://deavid.wordpress.com/2019/05/28/sedice-adding-fts-with-postgresql-was-really-easy/