НЕ В РЕАЛИЗАЦИИ Presto vs Spark SQL - PullRequest
5 голосов
/ 06 ноября 2019

Я получил очень простой запрос, который показывает значительную разницу в производительности при работе на Spark SQL и Presto (3 часа против 3 минут) на одном оборудовании.

SELECT field 
FROM test1 
WHERE field NOT IN (SELECT field FROM test2)

После некоторого исследования плана запросов я выяснил, что причина в том, как Spark SQL работает с подзапросом предиката NOT IN. Чтобы правильно обработать NULL из NOT IN, Spark SQL переводит предикат NOT IN как Left AntiJoin( (test1=test2) OR isNULL(test1=test2)).

В Spark SQL вводится OR isNULL(test1=test2) для обеспечения правильной семантики NOT IN.

Однако, OR предиката соединения Left AntiJoin приводит к единственно возможной стратегии физического соединения для Left AntiJoin - BroadcastNestedLoopJoin. Для текущей стадии я мог бы переписать NOT IN в NOT EXISTS, чтобы обойти эту проблему. В плане запроса NOT EXISTS я мог видеть предикат соединения Left AntiJoin(test1=test2), который заставляет лучший оператор физического соединения для NOT EXISTS (5 минут до конца).

Пока что мне повезло, так как мой набор данныхв настоящее время не имеет атрибутов NULL, но может иметь в будущем, и семантика NOT IN - это то, что я действительно хочу.

Поэтому я проверяю план запросов Presto, он на самом деле не предоставляет Left AntiJoin но он использует SemiJoin с FilterPredicate = not (expr). План запросов Presto не предоставляет слишком много информации, такой как Spark.

Так что мой вопрос больше похож на:

Могу ли я предположить, что в Presto есть лучший оператор физического соединения для обработки операции NOT IN? В отличие от Spark SQL, он не использует перезапись предикатов соединения isnull(op1 = op2) для обеспечения правильной семантики NOT IN на уровне логического плана.

1 Ответ

6 голосов
/ 06 ноября 2019

Я на самом деле человек, который внедрил NULL обработку для полусоединения (предикат IN) в Presto.

Presto использует режим репликации "дублировать нули и любые строки" в дополнение к хеш-разбиению¹,что позволяет ему правильно обрабатывать IN при наличии NULL s по обе стороны от IN, не возвращаясь к широковещанию или не делая выполнение однопоточным или одноузловым. Производительность во время выполнения практически такая же, как если бы NULL значений вообще не существовало.

Если вы хотите узнать больше о внутренностях Presto, присоединитесь к каналу #dev на Presto Community Slack.

¹), если быть точным, полусоединение разделено на хэш или транслируется в зависимости от решения или конфигурации на основе стоимости.

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