Физический план и оптимизация неравномерного соединения в Spark SQL

#apache-spark #apache-spark-sql

#apache-spark #apache-spark-sql

Вопрос:

Я использую Spark SQL 2.4.0. У меня есть пара таблиц, как показано ниже:

Таблица CUST:

 id | name | age | join_dt
-------------------------
12 | John | 25 | 2019-01-05
34 | Pete | 29 | 2019-06-25
56 | Mike | 35 | 2020-01-31
78 | Alan | 30 | 2020-02-25
  

Таблица ССЫЛОК:

 eff_dt
------
2020-01-31
  

Требуется выбрать все записи, из CUST которых join_dt есть <= eff_dt в REF таблице. Итак, для этого простого требования я составил следующий запрос:

версия #1:

 select 
c.id, 
c.name, 
c.age, 
c.join_dt
from cust c
inner join ref r
on c.join_dt <= r.eff_dt;
  

Теперь это создает BroadcastNestedLoopJoin в физическом плане, и, следовательно, для обработки запроса требуется много времени.

Вопрос 1:

Есть ли лучший способ реализовать эту же логику без BNLJ индуцирования и выполнить запрос быстрее? Возможно ли облегчить BNLJ ?

Часть 2:

Теперь я разбил запрос на 2 части следующим образом:-

версия #2:

 select c.id, c.name, c.age, c.join_dt
from cust c
inner join ref r
on c.join_dt = r.eff_dt --equi join
union all
select c.id, c.name, c.age, c.join_dt
from cust c
inner join ref r
on c.join_dt < r.eff_dt; --theta join
  

Теперь для запроса в Version#1 физический план показывает, что CUST таблица сканируется только один раз, тогда как физический план для запроса в Version#2 указывает, что одна и та же входная таблица CUST сканируется дважды (по одному разу для каждого из 2 запросов, объединенных с union ). Однако я с удивлением обнаружил, что это Version#2 выполняется быстрее, чем version#1 .

Вопрос 2:

Как version#2 выполняется быстрее, чем version#1 хотя version#2 сканирует таблицу дважды, в отличие от одного раза в случае version#1 , а также тот факт, что обе версии вызывают BNLJ ?

Может кто-нибудь, пожалуйста, уточнить. Пожалуйста, дайте мне знать, если требуется дополнительная информация. Спасибо.

Комментарии:

1. Сколько записей в ref таблице?

2. будет только 1 запись

3. Возможно ли для вас собрать ref строку таблицы в переменную? Затем, используя filter , вы могли бы вообще избежать объединения.

4. @Izhar Ahmed спасибо за ваш ответ. Поскольку мы используем запросы Spark SQL API, у меня нет возможности указывать эту дату в переменной. Кстати, сможете ли вы пролить свет на мой вопрос № 2, пожалуйста?