На основе чего принимается решение переписать SQL запрос
Что проверяют
Принимаете ли вы решение по измерению или по ощущению, и знаете ли, что в приложениях на Java источник медленного SQL чаще не сам запрос, а слой доступа к данным. Хороший кандидат сначала объясняет, как понял, что проблема именно здесь, и только потом говорит, что переписал.
Как отвечать
Переписывать имеет смысл, когда сошлись три условия.
Есть измерение: медленный эндпоинт виден в трассировках или мониторинге, запрос всплыл в pg_stat_statements или в логе медленных запросов. Приоритет по суммарному времени, а не по худшему разу: частый средний запрос обычно дороже редкого тяжёлого.
План объясняет причину: EXPLAIN (ANALYZE, BUFFERS) показывает последовательное чтение большой таблицы, расхождение ожидаемого и фактического числа строк, сортировку с выходом на диск, вложенный цикл на большом объёме. Без плана переписывание это лотерея.
Переписывание дешевле альтернатив. Часто задачу закрывает индекс, обновление статистики, пагинация по ключу вместо большого OFFSET или изменение требований к выборке.
Для Java добавьте отдельный пласт: если работа идёт через Hibernate, разбирайтесь с N+1 от ленивых связей, JOIN FETCH вместе с пагинацией, когда выборка целиком уезжает в память, отсутствием EntityGraph и batch size, выборкой полных сущностей там, где хватило бы проекции. Тут правится маппинг, а не текст запроса. Ещё две законные причины переписать: неверный результат и нечитаемый запрос, который уже трижды чинили.
Где спотыкаются
Первое: рассказывают про ускорение в разы без плана и без условий замера. На прогретом кэше и другом объёме данных цифра ничего не значит, а интервьюер попросит методику.
Второе: повторяют мифы. «Подзапрос всегда хуже соединения», «CTE ускоряет запрос». CTE это прежде всего читаемость, причём в части СУБД и версий он материализуется и мешает оптимизатору протолкнуть условия.
Третье: правят запрос на тестовой базе в сотню строк. Там любой план выглядит одинаково, и на проде улучшение не воспроизводится.