Spark task过多导致任务运行过慢甚至超时

背景以及现象

本文基于 spark 3.1.2
设置spark.driver.memory=2g
在调试spark sql任务的时候,发现有几个任务产生了40多万个Task,而且任务长期运行不出来。

分析

运行此sql,可以得到如下的dag(我们只截取产生Task多的Stage),由此可以看到是scan的文件太大了(scan了日志文件半年的数据)。
在这里插入图片描述

但是为什么这种情况下会导致任务运行很缓慢甚至会超时呢?
找到driver端,
用jstat -gcutil查看一下对应的gc情况(对应的内存都是调优完后的镜像信息),如下:

  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
 62.02   0.00   9.96  64.72  91.02  94.29    916   13.091    26    0.650   13.742
  0.00  77.27   6.58  64.72  91.02  94.29    917   13.100    26    0.650   13.750
  0.00  77.27  76.70  64.72  91.02  94.29    917   13.100    26    0.650   13.750
  0.00  22.28  45.52  65.65  91.02  94.29    921   13.143    26    0.650   13.794
  0.00  43.36  70.04  65.65  91.02  94.29    923   13.157    26    0.650   13.807
 63.00   0.00  71.39  65.65  91.02  94.29    924   13.165    26    0.650   13.815
  0.00  87.35  42.71  65.65  91.02  94.29    925   13.173    26    0.650   13.823
 21.96   0.00   0.00  66.59  91.02  94.29    930   13.220    26    0.650   13.871
 62.19   0.00   7.41  66.59  91.02  94.29    932   13.235    26    0.650   13.886
 62.19   0.00  65.55  66.59  91.02  94.29    932   13.235    26    0.650   13.886

直接用jmap -heap 命令查看一下对应的堆情况:

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 4294967296 (4096.0MB)
   NewSize                  = 172621824 (164.625MB)
   MaxNewSize               = 523436032 (499.1875MB)
   OldSize                  = 345374720 (329.375MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 155385856 (148.1875MB)
   used     = 115967072 (110.59481811523438MB)
   free     = 39418784 (37.592681884765625MB)
   74.63167818826444% used
Eden Space:
   capacity = 138149888 (131.75MB)
   used     = 100616000 (95.95489501953125MB)
   free     = 37533888 (35.79510498046875MB)
   72.83103986302181% used
From Space:
   capacity = 17235968 (16.4375MB)
   used     = 15351072 (14.639923095703125MB)
   free     = 1884896 (1.797576904296875MB)
   89.06417092442966% used
To Space:
   capacity = 17235968 (16.4375MB)
   used     = 0 (0.0MB)
   free     = 17235968 (16.4375MB)
   0.0% used
concurrent mark-sweep generation:
   capacity = 3127533568 (2982.6484375MB)
   used     = 2325934584 (2218.1840744018555MB)
   free     = 801598984 (764.4643630981445MB)
   74.36961213776492% used

可以看到driver端的内存 full gc频次有点高,而且内存增长的很厉害。

再次 我们用jmap -dump:format=b,file=heapdump.hprof命令dump内存的堆信息,我们分析一下,用MAT打开,我们可以看到如下的信息:
在这里插入图片描述
在这里插入图片描述
可以看到 taskSetManager的内就占用了700M。而且这任务才只是开始运行,所以后续很长一段时间,必然会占比较长的时间段。
而且这只是一个taskSetManager的内存占用,如果在足够复杂的sql下,有可能会有类似的taskSetManaget会有多个(taskSetManager是一个stage所有task的总和)。

结论以及解决方法

所以在这种情况下,如果业务上改变不了,我们就得增加内存,在笔者的情况下,增加driver内存到4g就能很好的解决,且运行的速度很快。

spark.driver.memory=4g
<think>好的,我需要帮助用户解决Hive查询性能差异的原因以及如何优化Java程序中通过YML文件连接Hive数据库的配置。首先,我需要理清Hive查询性能差异的可能因素。Hive是基于Hadoop的数据仓库工具,性能受多个方面影响,比如数据倾斜、分区和分桶策略、文件格式、资源配置、执行引擎以及查询语句本身的优化等。需要逐一分析这些因素。 然后,用户提到Java程序中通过YML文件连接Hive的配置。YML通常用于Spring Boot项目,配置数据源连接。这里需要检查连接池配置、Hive JDBC参数、资源分配以及可能的Kerberos认证设置。比如连接池的大小不合理可能导致性能问题,JDBC的超时设置不正确会影响查询响应。 接下来,我需要结合引用中的内容。引用[1]提到了内存数据库、CQRS模式、事件溯源等优化策略,虽然这些主要针对实时系统,但可以部分借鉴,比如使用更高效的数据存储格式(如ORC、Parquet)来优化Hive查询。引用[2]提到分库分表,但Hive本身是数据仓库,分区分桶可能更相关,不过DAL框架的问题可能提醒要注意避免ORM的笨重,保持查询的灵活性。 在解决方案部分,需要分点说明性能优化的方法,包括数据模型优化、配置参数调整、执行引擎选择(如Tez或Spark)、资源管理和查询优化技巧。对于YML配置,要给出具体的配置示例,如Hikari连接池的参数,以及Hive JDBC的URL格式,确保用户能直接应用。 最后,生成相关问题时要围绕Hive性能调优和配置,可能涉及执行引擎比较、数据倾斜处理、文件格式选择等,确保问题覆盖用户可能进一步的需求。</think>### Hive查询性能差异原因分析及优化方案 #### 一、Hive查询性能差异的主要原因 1. **数据分布特征** - 数据倾斜会导致某些Reduce任务负载过高,形成长尾效应$^{[典型场景]}$ - 未使用分区表或分桶表时,全表扫描会显著增加IO开销 2. **执行引擎差异** - MapReduce引擎与Tez/Spark引擎性能对比: $$T_{MR} = N_{map} \times t_{map} + N_{reduce} \times t_{reduce}$$ $$T_{Tez} = \sum_{stage} (并行化流水线执行时间)$$ 3. **配置参数影响** - `hive.exec.parallel`(是否启用并行执行) - `hive.auto.convert.join`(自动优化MapJoin) - `hive.vectorized.execution.enabled`(向量化执行) #### 二、YML连接配置优化示例 ```yaml spring: datasource: hive: jdbc-url: jdbc:hive2://hiveserver:10000/default;tez.queue.name=prod driver-class-name: org.apache.hive.jdbc.HiveDriver hikari: maximum-pool-size: 20 # 根据集群规模调整 connection-timeout: 30000 validation-timeout: 5000 properties: hive.resultset.use.unique.column.names: false hive.fetch.task.conversion: more ``` #### 三、性能优化实施路径 1. **数据模型优化** - 建立分层分区(年/月/日) - 对高频查询字段进行分桶 - 使用ORC文件格式并创建布隆过滤器 2. **执行参数调优** ```sql SET hive.vectorized.execution.enabled=true; SET hive.optimize.sort.dynamic.partition=true; SET hive.auto.convert.join.noconditionaltask.size=512000000; ``` 3. **资源管理策略** - YARN队列资源配置(参考引用[1]的实时监控方案) - 结合CQRS模式分离读写操作(如引用[1]所述) 4. **查询优化技巧** - 避免`SELECT *`查询 - 使用谓词下推(Predicate Pushdown) - 对JOIN操作进行顺序优化 #### 四、配置验证方法 1. 使用`EXPLAIN`解析执行计划 2. 通过HiveServer2日志分析连接问题 3. 使用JMeter进行JDBC压力测试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值