Spark:为什么使用“NOT IN”的子查询比“IN”慢得多?

3

我在Apache Spark 2.x中有两个表格。每个表格都有一个共同的行“IDNUM”。称它们为A表格和B表格。

以下是Apache SparkSQL中的快速查询:

SELECT COUNT(*) FROM A where IDNUM IN (SELECT IDNUM FROM B);

这非常慢:
SELECT COUNT(*) FROM A where IDNUM NOT IN (SELECT IDNUM FROM B);

这个操作太慢了,直接完成反而更快:

total = SELECT COUNT(*) FROM A;
quan  = SELECT COUNT(*) FROM A where IDNUM IN (SELECT IDNUM FROM B);
print(total-quan)

但我无法理解为什么使用 NOT IN 会如此缓慢。


你有一些样本基准测试可以展示它慢多少吗?2倍,10倍? - Raj
看起来大约是10倍到100倍。 - vy32
请编辑您的问题并提供一个MCVE - 如何制作可重复的Apache Spark示例 提供了许多有用的提示,包括但不限于提供执行计划。在这种特定情况下,我还建议解释数据如何加载,如何进行基准测试,并包括相关配置(至少与自适应和基于成本的执行相关的配置)。 - zero323
2
我已经注意到几次,Spark 在执行 NOT IN 语句时有时会非常慢,而使用 JOIN B ON A.IDNUM = B.IDNUM WHERE B.IDNUM is null 编写等效查询可能会快得多。 你应该尝试一下,看看它是否对你也更快。 - FurryMachine
1个回答

1
我不了解Apache Spark,但是看起来数据库可以通过IDNUM快速访问A和B中的行/项,因此如果通过'IDNUM IN (SELECT IDNUM FROM B)'条件筛选出的元素数量很少,那么检查相等的子查询或连接可以非常快速地处理。获取整个表的计数是一个常见的情况,因此它将被优化为快速。
'IDNUM NOT IN (SELECT IDNUM FROM B)'天真地需要扫描所有A中的行的IDNUM列,以检查它们是否不在B的集合中。由于您只需要计算总数,因此您实际上不需要这些行的IDNUM值,但我猜查询优化器不够聪明,无法将查询转换为两个计数之间的差异。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接