Имеет ли смысл менять порядок условий в запросе
Что проверяют
Понимаете ли вы разницу между условиями в SQL, где порядок выбирает оптимизатор, и логическими выражениями в Java, где порядок вычисления строго задан. Следом обычно спрашивают про составной индекс и порядок колонок в нём.
Как отвечать
Разделите ответ на две части.
В SQL порядок условий в WHERE на план почти не влияет. Запрос декларативный, оптимизатор сам решает, какой индекс взять и что проверять первым. WHERE status = 'NEW' AND user_id = 42 и тот же запрос с переставленными условиями дадут одинаковый план. Важные уточнения:
- составной индекс: значение имеет порядок колонок в самом индексе, а не в
WHERE. Индекс по(user_id, status)поможет фильтру поuser_idи по паре, но не по одномуstatus; - короткое замыкание не гарантировано: стандарт SQL не обещает вычислять условия слева направо.
WHERE qty <> 0 AND total / qty > 10может упасть делением на ноль, защищаться нужно черезCASEилиNULLIF; - соединения: PostgreSQL переставляет
JOINсам, пока их не большеjoin_collapse_limit(по умолчанию 8). В очень больших запросах порядок записи начинает влиять на план; - проверка: не гадать, а смотреть
EXPLAIN (ANALYZE, BUFFERS)до и после.
В Java && и || вычисляются слева направо с коротким замыканием. Здесь порядок важен: первым ставят дешёвое и чаще отсекающее условие, а проверку на null строго перед обращением к объекту: user != null && user.isActive(). То же в цепочке stream().filter(...): дешёвый и селективный фильтр раньше.
Где спотыкаются
Переставляют условия в WHERE, чтобы помочь базе, и называют это оптимизацией. Без изменения индексов или самого запроса план останется прежним, что сразу видно по EXPLAIN.
Переносят логику Java на SQL и рассчитывают, что правое условие не вычислится, если левое ложно. В SQL на это полагаться нельзя.
В Java, наоборот, считают порядок неважным и ставят поход в базу или внешний сервис перед простой проверкой флага. Лишний сетевой запрос на каждом вызове обходится дороже, чем кажется.