为什么Hive警告此子查询会导致笛卡尔积?

时间:2019-01-13 21:51:25

标签: hive hiveql

根据Hive的documentation,它支持NOT IN子句中的WHERE子查询,条件是子查询是不相关的子查询(不引用主查询中的列)。

但是,当我尝试运行下面的琐碎查询时,出现错误FAILED: SemanticException Cartesian products are disabled for safety reasons.

-- sample data
CREATE TEMPORARY TABLE foods (name STRING);
CREATE TEMPORARY TABLE vegetables (name STRING);

INSERT INTO foods VALUES ('steak'), ('eggs'), ('celery'), ('onion'), ('carrot');
INSERT INTO vegetables VALUES ('celery'), ('onion'), ('carrot');

-- the problematic query
SELECT *
FROM foods
WHERE foods.name NOT IN (SELECT vegetables.name FROM vegetables)

请注意,如果我使用IN子句而不是NOT IN子句,它实际上可以正常工作,这很令人困惑,因为在任何情况下查询评估结构都应该相同。

是否有解决方法,或者是基于值在另一个表中从查询中筛选值的另一种方法?

这是在Amazon EMR集群上运行的Hive 2.3.4 btw。

2 个答案:

答案 0 :(得分:1)

不确定为什么会收到该错误。一种解决方法是使用not exists

SELECT f.*
FROM foods f
WHERE NOT EXISTS (SELECT 1 
                  FROM vegetables v
                  WHERE v.name = f.name)

left join

SELECT f.*
FROM foods f 
LEFT JOIN vegetables v ON v.name = f.name
WHERE v.name is NULL

答案 1 :(得分:0)

您获得了笛卡尔加入,因为这是Hive在这种情况下所做的。 vegetables表很小(仅一行),正在广播以执行交叉(很可能是map-join,检查计划)连接。 Hive会先交叉(映射)连接,然后应用过滤器。带有@VamsiPrabhala表示的过滤器的显式左联接语法将强制执行左联接,但是在这种情况下,它的作用相同,因为表非常小,并且CROSS JOIN不会将行相乘。

对查询执行EXPLAIN,您将看到实际发生的情况。