Оба действительны и в случае INNER JOIN и PPD оба будут работать одинаково.Но эти методы работают по-разному в случае условия соединения OUTER JOINS
ON до соединения.
ГДЕ применяется после объединения.
Оптимизатор решает, применимо ли Predicate push-down или нет, и это может сработать, но в случае LEFT JOIN, например, с фильтром WHERE на правой таблице, фильтр WHERE
SELECT * FROM a
LEFT JOIN b ON a.some_id=b.some_other_id
WHERE b.some_name=6 --Right table filter
будет ограничивать NULL, а LEFT JOIN
будет преобразован в INNER JOIN
, потому что если b.some_name = 6, он не может быть NULL.
И PPDне изменяет это поведение.
Вы все еще можете выполнить LEFT JOIN с фильтром WHERE, если добавите дополнительное условие ИЛИ, разрешающее пустые значения в правой таблице:
SELECT * FROM a
LEFT JOIN b ON a.some_id=b.some_other_id
WHERE b.some_name=6 OR b.some_other_id IS NULL --allow not joined records
И если у вас естьмножественные объединения со многими такими условиями фильтрации, подобная логика делает ваш запрос трудным для понимания и удаления ошибок.
СЛЕДУЮЩЕЕ СОЕДИНЕНИЕ с фильтром ON не требует дополнительного условия ИЛИ, так как он фильтрует правую таблицу перед объединением, этот запрос работает какожидается и легко понять:
SELECT * FROM a
LEFT JOIN b ON a.some_id=b.some_other_id and b.some_name=6
PPD по-прежнему работает для фильтра ON, и если таблица b имеет значение ORC, PPD переведет предикат на минимально возможный уровень в ORCЧитатель и будет использовать встроенные ORC-индексы для фильтрации на трех уровнях: строки, полосы и файлы.
Подробнее по той же теме и некоторые тесты: https://stackoverflow.com/a/46843832/2700344
Итак,PPD или не PPD, лучше использовать явный синтаксис ANSI с условием ON и фильтрацией ON, если это возможно, чтобы максимально упростить запрос и избежать непреднамеренного преобразования в INNER JOIN.