Spark JDBC读取Teradata写入HDFS ORC性能优化相关问题咨询
问题1解答
Spark的计算是懒加载的,写ORC属于Action操作,是否会触发每个分区单独发起JDBC调用分两种情况:
- 若读取Teradata生成的4~5个DataFrame未执行过
cache()/persist()缓存操作:触发写ORC时会重跑全链路DAG,每个JDBC读取分区都会独立发起JDBC连接拉取数据,逻辑和foreachPartition的分区级独立执行逻辑一致。 - 若之前已经对读取生成的DataFrame做了缓存:触发写ORC时会直接读取缓存中的数据,不会再向Teradata发起JDBC请求。
问题2解答
针对task数据量过大导致OOM的问题,可从以下角度优化:
- 调整shuffle分区数:当前设置的1000个分区对应单分区超2GB,可将
spark.sql.shuffle.partitions调整为2000~3000,把单分区数据量控制在1GB以内,降低单个task的内存压力。 - 开启Spark自适应查询(AQE):Spark3.x以上版本开启AQE后,可自动识别倾斜大分区并做拆分,同时自动合并小分区,适配实际数据分布减少OOM概率。
- 优化内存配置:将序列化方式换成Kryo序列化,降低对象内存占用;适当调大
spark.executor.memoryOverhead堆外内存比例,满足大分区序列化、文件写入的内存开销。 - 写ORC时开启压缩:配置
spark.sql.orc.compression.codec为snappy或zstd,降低写入IO开销的同时减少中间数据的内存占用。
问题3解答
适配Teradata 300并发会话上限的方案如下:
- 控制JDBC读取并发数:配置JDBC读的
numPartitions参数不超过250(预留部分会话余量),避免单次读取就占满会话上限。 - 串行读取多DataFrame:4~5个源DataFrame不要并行触发读取,读完1个后先持久化到
MEMORY_AND_DISK_SER,再触发下一个DataFrame的读取,保证同一时间只有最多250个并发连接请求Teradata。 - 限制Spark执行并发:关闭动态资源分配或配置
spark.dynamicAllocation.maxExecutors,结合每个executor的核数设置,保证同一时间运行的task总数不超过250,避免并发连接超限。 - 配置JDBC连接池:在JDBC参数中配置连接池复用逻辑,减少重复新建连接的开销,同时避免并发连接数溢出。
内容的提问来源于stack exchange,提问作者Swastik Mohanty
相关产品推荐
相关产品推荐

