Предикат Pushdown против пункта - PullRequest
2 голосов
/ 28 апреля 2019

При выполнении объединения в Hive и последующей фильтрации вывода с помощью предложения where компилятор Hive попытается отфильтровать данные до объединения таблиц. Это называется предикатом pushdown (http://allabouthadoop.net/what-is-predicate-pushdown-in-hive/)

Например:

SELECT * FROM a JOIN b ON a.some_id=b.some_other_id WHERE a.some_name=6

Строки из таблицы a, имеющие some_name = 6, будут отфильтрованы перед выполнением объединения, если включены предикаты push-down (hive.optimize.ppd).

Однако недавно я также узнал, что существует другой способ фильтрации данных из таблицы перед ее соединением с другой таблицей (https://vinaynotes.wordpress.com/2015/10/01/hive-tips-joins-occur-before-where-clause/).

Можно указать условие в условии ON, и таблица a будет отфильтрована до выполнения объединения

Например:

SELECT * FROM a JOIN b  ON a.some_id=b.some_other_id AND a.some_name=6

Обеспечивают ли оба эти параметра оптимизацию предиката?

Спасибо

1 Ответ

1 голос
/ 28 апреля 2019

Оба действительны и в случае 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...