OR 目前在 Hive 中的 JOIN 错误中不受支持

问题描述

我正在 Hive 中运行一个查询,如下所示,并且在左连接中有 OR 条件。当我运行选择时,它会向我抛出几条错误消息。

  1. OR 目前在 JOIN 中不受支持(了解 OR 仅适用于 Hive 中的 equi 连接)

  2. JOIN 'cre_timestamp' 中同时遇到左右别名

           a.line_id,a.seller,a.sellerid,a.sellername,a.item_no,a.item_cd,a.cre_timestamp
     from Table A
     left join Table B
     on translate(a.id,'0','') = translate(b.id,'')
     or translate(a.seller,'Z','') = translate(b.seller,'')
     or (a.item_no=b.item_no and a.item_no is not null and a.item_cd is not null and a.item_no <> '' and a.item_cd <> '')
     left join ( select id,line_id,cre_timestamp from table x) C
     on a.id=c.id
     and a.cre_timestamp < c.cre_timestamp
     and a.cre_timestamp > date_sub(c.cre_timestamp,21)
     and translate(a.id,'') or a.item_cd = b.item_cd
    where a.seller is null

我们如何克服这个问题?

#对于 1: 我可以尝试编写查询的一种方法是,使用 UNION,将查询复制 3 次,用于 OR 条件。

#For 2:

如果我剪了

and a.cre_timestamp < c.cre_timestamp
     and a.cre_timestamp > date_sub(c.cre_timestamp,21)

并将其放入底部where 子句中,它工作正常。 (想了解为什么它在连接中不起作用)

总的来说,寻找更好的方法,不会影响运行时和更优化的查询,就像我将其更改为使用UNION一样,它必须处理相同的查询3次,这会影响查询.

感谢您花时间研究这个问题。

解决方法

我已经在这篇文章中解释过为什么非等 (theta) 连接在 map-reduce 框架中不起作用,这里不再重复,请阅读:Why Hive can not support non-equi join

现在如果您将非等式连接条件移到 where 子句中会发生什么:连接将仅使用等式条件工作,并且可能会产生一些重复,因为它可以是多对多连接。这些重复项将被 WHERE 条件过滤。在最坏的情况下,如果您根本没有相等条件,则会执行CROSS JOIN,这也很容易使用MapReduce框架实现,之后您可以过滤where中的行。过滤也很容易实现。

这是目前在 Hive 中实现 Theta-join 的唯一方法:在部分相等条件(甚至 CROSS JOIN)上使用重复连接加上过滤,这种方法会对性能产生重大的负面影响。但是,如果其中一个表小到足以放入内存,您可以使用 map-join 补偿对性能的负面影响:

set hive.auto.convert.join=true;
set hive.mapjoin.smalltable.filesize=1000000000; --small table size which can fit in memory,--adjust it and check Map Join operator in the plan

此外(这与问题无关)您的查询中有多余的条件:

(a.item_no=b.item_no and a.item_no is not null and a.item_cd is not null and a.item_no <> '' and a.item_cd <> '')

a.item_no is not null - 在这里没有任何用处,因为 1) 此列已在等式连接条件中使用并且未连接 NULL,2) 还有另一个条件 a.item_no <> '' 排除了 NULL,因为如果值不等于空字符串,也不能为NULL,NULL不能等于或不等于某物。

相同的冗余条件 a.item_cd is not null 因为您已经有了 a.item_cd <> '',这不允许 NULL。

所以,整个条件可以简化为这个:

(a.item_no=b.item_no and a.item_no <> '' and a.item_cd <> '')

是的,将查询拆分为两个或多个 + UNION 是解决 OR 连接条件问题的常用方法。如果你有一些常用的过滤器,你可以使用 WITH 子查询来补偿多次扫描整个表。使用不同的过滤器和连接条件 + UNION 或 UNION ALL 拆分数据集也有助于偏斜连接键。如果您使用 Tez,使用 WITH 子查询将允许读取表一次(在映射器上),所有其他顶点将读取由映射器准备的相同结果,从而避免每次将中间结果写入持久性存储。