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

kh212irz  于 2021-06-27  发布在  Hive
关注(0)|答案(2)|浏览(616)

根据hive支持的文档 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` 子句中,它实际上工作得很好,这是令人费解的,因为在这两种情况下,查询求值结构应该是相同的。
是否有解决方法,或者根据查询中的值在另一个表中的存在情况筛选这些值的其他方法?
这是Hive2.3.4 btw,运行在AmazonEMR集群上。
mnemlml8

mnemlml81#

你得到了笛卡尔连接,因为这就是Hive在这种情况下所做的。 vegetables 表非常小(只有一行),正在广播它以执行交叉连接(很可能是Map连接,检查计划)连接。配置单元先交叉(Map)连接,然后应用过滤器。@vamsiprabhala所说的带有filter的显式左联接语法将强制执行左联接,但在本例中,它的工作原理是相同的,因为表非常小,交叉联接不会使行相乘。
对您的查询执行explain,您将看到到底发生了什么。

zxlwwiss

zxlwwiss2#

不知道为什么会出现这样的错误。一个解决方法是使用 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

相关问题