首页 > 数据库 >【Spark SQL】Join连接条件使用or导致运行慢

【Spark SQL】Join连接条件使用or导致运行慢

时间:2025-01-10 10:45:24浏览次数:1  
标签:city Join t2 t1 SQL Spark null type id

现象

运行的SQL示例如下

select
  t1.*
from edw.a t1
left join edw.b t2
on (t1.id = t2.id or ((t1.id is null or t2.id is null) and t1.phone = t2.phone))
and t1.province = t2.province
and t1.city = t2.city
and t1.type = t2.type
where t2.type is null
;

提交运行后发现部分task时间非常久。
在Spark UI上观察执行情况,发现join上的数据超过1000亿。

检查执行计划,发现分区过程只用到了city、type、province三个字段,没有用到id和phone字段。

由于city、type、province三个字段重复值特别多,导致关联上的数据特别多。
解决方案
修改SQL
错误改法:使用union把两部分合并
因为这里用到了or,容易想到进行union操作

select
  t1.*
from edw.a t1
left join edw.b t2
on t1.id = t2.id 
and t1.province = t2.province
and t1.city = t2.city
and t1.type = t2.type
where t2.type is null
union
select
  t1.*
from edw.a t1
left join edw.b t2
on (t1.id is null or t2.id is null) 
and t1.phone = t2.phone
and t1.province = t2.province
and t1.city = t2.city
and t1.type = t2.type
where t2.type is null
;

执行之后发现结果不符合预期,最后输出的结果就是edw.a表的全量数据。
问题在于逻辑中是取没有匹配上的数据t2.type is null,操作等于取两个条件并集的补集,而合并后是取两个条件补集的并集,最后得到了全集。
正确改法:使用两个join关联

select
  t1.*
from edw.a t1
left join edw.b t2
on t1.id = t2.id 
and t1.province = t2.province
and t1.city = t2.city
and t1.type = t2.type
left join edw.b t3
on (t1.id is null or t3.id is null) 
and t1.phone = t3.phone
and t1.province = t3.province
and t1.city = t3.city
and t1.type = t3.type
where t2.type is null
and t3.type is null
;

改动后

  1. join中会用到id和phone作为shuffle的条件,匹配到的数据量减少,执行速度大幅提高。
  2. 输出的数据符合预期。

标签:city,Join,t2,t1,SQL,Spark,null,type,id
From: https://www.cnblogs.com/julytiantian/p/18663541

相关文章

  • SQLSERVER截取q前300字节长度
    在SQLServer中,如果你想截取一个字符串的前300个字节,可以使用LEFT函数结合DATALENGTH函数来实现。LEFT函数用于从字符串的左侧开始截取指定长度的字符,而DATALENGTH函数用于获取字符串的实际字节长度。示例假设有一个表Articles,其中有一个varchar类型的字段Conten......
  • pgsql 主从
    vim/home/opt/postgresql-16.0/data/postgresql.conf#设置以下listen_addresses='*'#允许远程连接hot_standby=on#打开热备wal_level=replica#设置WAL日志级别为replicamax_wal_senders=3#允许的WAL发送者数量,根据需要进行调整archive_mode=onarc......
  • 服务器上mysqld,java的进程Out of Memory,被kernel kill 掉了
    /var/log/messages里面日志如下Aug1019:47:16VM-0-7-centoskernel:8936totalpagecachepagesAug1019:47:16VM-0-7-centoskernel:0pagesinswapcacheAug1019:47:16VM-0-7-centoskernel:Swapcachestats:add0,delete0,find0/0Aug1019:47:16VM-0......
  • 使用mysqlbinlog 备份 binlog日志文件
    使用mysqlbinlog备份二进制日志文件默认情况下,mysqlbinlog读取二进制日志文件并以文本格式显示其内容。这使您能够更轻松地检查文件中的事件并重新执行它们(例如,通过将输出用作mysql的输入)。mysqlbinlog可以直接从本地文件系统读取日志文件,或者,--read-from-remote-server它可......
  • MySQL三种读取模式详解:普通、流式、游标
    在与MySQL数据库交互时,数据的读取方式有多种选择,包括普通读取、流式读取和游标读取。每种方式都有其独特的原理、优势和劣势。本文将对这三种读取方式进行详细介绍,并通过示例代码展示它们的使用方法和运行结果。1.普通读取介绍普通读取是指通过JDBC的Statement或Prepare......
  • 35岁重学网络安全——SQL注入篇(三)
    浪子回头金不换,35岁重学网络安全——SQL注入篇。本篇内容简介:MYSQL中的查询相关操作以及一些常用函数。实验环境在security库中做下列测试:usesecurity;PS:如果已经成功安装了sqli-labs的靶场,在Mysql中已经存在security库。基本查询#select+列名(*代表所有)from表......
  • 35岁重学网络安全——SQL注入篇(二)
    浪子回头金不换,35岁重学网络安全——SQL注入篇。本篇内容简介:MYSQL中库、表、行和列的基本概念与相关操作基本概念库(Database):库是数据存储的最高级别,可以看作是一个容器,用于存储相关的表集合。一个MySQL服务器可以有多个数据库,每个数据库可以独立管理,互不干扰。例如,一个......
  • 如何通过宝塔面板定时任务重启MySQL服务以保持稳定性和优化性能
    MySQL服务在长时间运行后,可能会因为各种原因导致连接不稳定或内存占用过大,影响网站和应用程序的性能。为了确保MySQL服务的稳定性和优化性能,可以通过宝塔面板设置定时任务来定期重启MySQL服务。以下是具体的操作步骤和建议:理解定时重启的好处:定期重启MySQL服务可以帮助清理缓存......
  • MySQL中的事务和事务隔离级别
    MySQL/MariaDB中的事务和事务隔离级别 分类: 数据库系列undefined官方手册:https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-transaction-model.html1.事务特性事务具有ACID特性:原子性(A,atomicity)、一致性(C,consistency)、隔离性(I,isolation)、持久性(D,......
  • 有效解决 PbootCMS 网站提示“执行SQL发生错误!错误:DISK I/O ERROR”的问题
    定期清理缓存定期手动清理缓存文件,确保磁盘空间不会被占用过多。可以通过后台管理系统的“系统设置”模块进行清理。监控磁盘空间使用系统监控工具(如 df-h 命令)定期检查磁盘空间使用情况。确保有足够的磁盘空间来存储网站文件和数据库。优化数据库定期优化S......