Два запроса ищут пользователей без заказов: LEFT JOIN orders ON ... WHERE orders.id IS NULL и WHERE NOT EXISTS (SELECT 1 FROM orders WHERE ...). Что верно о производительности в PostgreSQL?

AОптимизатор PostgreSQL обычно сводит оба варианта к плану Anti Join, разница в скорости минимальна
BВариант с LEFT JOIN ... IS NULL быстрее: NOT EXISTS запускает подзапрос для каждой строки
CВариант с NOT EXISTS быстрее: он прерывает поиск в подзапросе на первом совпадении
DОба варианта выполняются последовательно: сначала полный JOIN, потом фильтр по IS NULL
Правильный ответ. Оптимизатор PostgreSQL обычно распознаёт оба паттерна как анти-соединение и строит одинаковый план — разница в скорости минимальна.

Разбор

Современные оптимизаторы (PostgreSQL, SQL Server, Oracle) умеют преобразовывать LEFT JOIN ... IS NULL, NOT EXISTS и даже NOT IN (без NULL) в один оператор Anti Join. В выводе EXPLAIN это видно как Hash Anti Join или Merge Anti Join. На практике для PostgreSQL разница в скорости между первыми двумя подходами пренебрежимо мала. NOT IN может проиграть из-за обработки NULL. Рекомендация: выбирать наиболее читаемый вариант.

Проверь себя · 1/3разбор после ответа
Два запроса: SELECT * FROM orders JOIN users ON orders.user_id = users.user_id и SELECT * FROM orders JOIN users USING(user_id). В чём ключевое ограничение USING?
Тренировать SQL в Telegram

Ещё вопросы по теме «JOIN и операции множеств»