Spark SQL调优案例:单字段NOT IN子查询优化

本文探讨了一个Spark SQL查询优化案例,针对单字段NOT IN子查询导致的性能问题。原始SQL在处理百万级别数据时运行超过5小时。通过分析发现,优化器将其转化为BroadcastNestedLoopJoin,造成效率低下。解决方案是将NOT IN子查询改写为LEFT JOIN,变为SortMergeJoin,降低时间复杂度到O(n + nlogn)。在Spark 3.1.0中虽有改进,但在大数据量或Spark 2.4.0版本下仍需手动优化。

背景

有如下的数据查询场景。

表结构

create table order (order_id long, customer_id long) partitioned by (date string);

要查询当天有订单,但是前一天没有订单的用户在当天的订单记录。

数据分析的同事编写的最初版本的SQL如下

select * from order where date='2021-07-17' and customer_id not in (
    select customer_id from order where date='2021-07-16');

这张表每天的数据量大概在百万级别。

SQL在10个4Core16GB的executor上运行了5个多小时依然没有结束。    

分析

通过查看SQL语句的执行计划基本就可以判断性能瓶颈所在。

| == Physical Plan ==
BroadcastNestedLoopJoin BuildRight, LeftAnti, ((customer_id#370L = customer_id#373L) || isnull((customer_id#370L = customer_id#373L)))
:- Scan hive default.order [order_id#369L, customer_id#370L, date#371], HiveTableRelation `default`.`order`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [order_id#369L, customer_id#370L], [date#371], [isnotnull(date#371), (date#371 = 2021-07-17)]
+- BroadcastExc
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值