in-hive-sql-joining与不带udf的interval

chy5wohz  于 2021-06-27  发布在  Hive
关注(0)|答案(1)|浏览(334)

我遇到过这样一个练习,它要求将一个表中与事件相关的知识产权与另一个表中的国家知识产权范围相匹配。i、 e.它可能看起来像这样(简化):

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—据我所知,只有在包含表的范围适合内存的情况下才有可能。
虽然我知道如何编写自定义项,但我对这种方法并不满意。特别是它没有说明如果ranges表非常大(当然不是这种情况)并且不容易放入内存时该怎么办。
直观地看,除了hive之外,如果两个表都按ip排序,我们可以一次解决问题,保持“当前范围”,将所有即将到来的ip与之匹配,然后更新到下一个范围。这甚至应该很容易并行化。。。
所以我想知道,是否有一个依赖于hql本身的解决方案(也许在以后的hive版本中)。

up9lanfz

up9lanfz1#

配置单元中不允许非相等联接。而join without on condition是一个交叉连接,它将使行相乘,而应用于结果数据集的where子句将过滤大量行,例如x195(国家的数目),这将导致性能问题。
不过,在这种情况下,您可以尝试将交叉联接转换为Map联接,因为country表适合内存。解决方案是Map联接。小表将广播到每个Map器,加载到内存中并用于连接。说明应反映Map加入计划,核对一下。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;

相关问题