В Hive SQL - объединение с интервалами без UDF - PullRequest
0 голосов
/ 21 декабря 2018

Я натолкнулся на упражнение, в котором предлагается сопоставить связанные с событиями IP-адреса из одной таблицы с диапазонами IP-адресов стран из другой таблицы.Т.е. это может выглядеть так (упрощенно):

table: events

event_id  |  source_ip
----------------------
12345678  |  3.15.49.5
31234314  |  7.1.8.190

table: geoips

country  |  start_ip  |  end_ip
-----------------------------------
us       |  1.0.0.0   |  1.127.255.255
us       |  1.128.0.0 |  1.255.255.255
us       |  3.0.0.0   |  3.255.255.255

и мы хотим получить:

event_id  |  source_ip  |  country
----------------------------------
12345678  |  3.15.49.5  |  us
31234314  |  7.1.8.190  |  uk

Предположим, мы можем преобразовать IP в целые числа, чтобы упростить сравнение (или преобразовать в ноль)-пополненные строки, чтобы их можно было сравнивать в алфавитном порядке).

Так похоже на объединение on event_ip >= start_ip and event_ip <= end_ip.Однако, насколько я понимаю, в Hive это не сработает так просто, поскольку «поддерживаются только объединения с равенством».

Чаще всего (и в этом упражнении) предлагается использовать UDF - насколько я понимаю, это тольковозможно, если таблица с диапазоном помещается в памяти.

Хотя я знаю, как писать UDF, я не удовлетворен этим подходом.Тем более, что в нем не сказано, что делать, если таблица диапазонов очень велика (конечно, не в этом случае) и не умещается в памяти легко.

Интуитивно кажется, что, кроме Hive, еслиу нас есть обе таблицы, отсортированные по IP, мы можем решить проблему за один проход, поддерживая «текущий диапазон» и сопоставляя с ним все будущие IP-адреса, а затем обновляя до следующего диапазона.Это даже должно быть достаточно просто для распараллеливания ...

Так что мне интересно, если (возможно, в более поздних версиях Hive) есть решение, основанное на самом HQL.

1 Ответ

0 голосов
/ 21 декабря 2018

Соединения с неравенством не разрешены в Hive.И объединение без условия On является перекрестным соединением, оно будет умножать строки, а условие Where, примененное к результирующему набору данных, будет фильтровать большое количество строк, скажем, x195 (количество стран), и это вызовет проблемы с производительностью.

Однако в этом случае вы можете попытаться преобразовать CROSS join в map-join, потому что таблица стран помещается в памяти.Решением является MAP-JOIN.Небольшая таблица будет транслироваться каждому мапперу, загружаться в память и использоваться для объединения.EXPLAIN должна отражать MAP-JOIN в плане, проверьте его.Mapjoin будет работать быстро.

Используйте Tez, векторизованное выполнение, mapjoin и cbo:

set hive.cbo.enable=true;
set hive.execution.engine=tez;
set hive.vectorized.execution.enabled = true;
set hive.vectorized.execution.reduce.enabled = true;
set hive.compute.query.using.stats=true;
set hive.stats.fetch.column.stats=true;
set hive.stats.fetch.partition.stats=true;
set hive.optimize.ppd=true;
--enable mapjoin
set hive.auto.convert.join=true;

select e.event_id, e.source_ip, i.country
    from events e 
         cross join geoips i 
   where e.event_ip >= i.start_ip and e.event_ip <= i.end_ip;
...