Spark-Submit执行Scala Spark程序耗时远超IntelliJ,求优化建议
嘿,这个场景我太熟悉了!同样是用local[*]模式,IDE里跑1分钟,spark-submit却要4分钟,这种差异大多是环境配置或参数对齐的问题,咱们一个个排查调整:
1. 对齐JVM内存与GC参数
IntelliJ的Run Configuration里默认会给JVM分配相对合理的内存(说不定你还手动调过-Xmx),但spark-submit默认的driver内存只有1g左右,内存不足会导致频繁GC拖慢速度。
调整spark-submit命令,加上内存和GC参数:
spark-submit --master local[*] \ --driver-memory 4g \ --executor-memory 4g \ --conf "spark.driver.extraJavaOptions=-XX:+UseG1GC" \ your-app.jar
(local模式下executor和driver是同一个进程,但设置executor内存仍会生效,确保有足够内存处理250K条数据)
2. 优化JDBC读取的fetchSize参数
MySQL JDBC驱动默认的fetchSize很小(比如仅10条),拉取250K数据会产生上万次数据库往返,这是最常见的性能瓶颈!不管IDE还是spark-submit,都要在代码里显式设置:
val df = sparkSession.read.format("jdbc") .option("url", "jdbc:mysql://your-host/your-db") .option("dbtable", "your-table") .option("user", "username") .option("password", "password") .option("fetchSize", "10000") // 大幅减少数据库交互次数 .load()
这个参数对数据拉取速度的提升非常明显,大概率是你没注意到的关键优化点。
3. 降低日志输出开销
spark-submit默认的日志级别是INFO,会输出大量调试信息,IO开销会拖慢运行速度。你可以:
- 在代码里全局设置日志级别:
sparkSession.sparkContext.setLogLevel("WARN") - 或者在spark-submit命令里指定日志配置:
把log4j.properties里的根日志级别设为spark-submit --master local[*] \ --conf "spark.driver.extraJavaOptions=-Dlog4j.configuration=file:/path/to/your/log4j.properties" \ your-app.jarWARN即可。
4. 统一依赖包的加载方式
IDE会缓存Maven/Gradle的依赖包,启动时加载更快;而spark-submit如果用--packages参数,第一次运行会下载依赖,即使后续缓存,加载速度也可能不如IDE。建议把MySQL驱动等依赖打包成fat jar(比如用sbt-assembly或maven-shade-plugin),避免运行时动态拉取依赖的开销。
5. 检查系统资源占用
运行spark-submit时,看看终端所在的环境是否有其他进程占用大量CPU/内存?比如后台跑了其他任务,导致Spark无法充分利用资源。可以用top或任务管理器查看资源使用率,确保运行Spark时系统资源充足。
先从fetchSize和JVM内存这两个点入手调整,应该能快速缩小差异!
内容的提问来源于stack exchange,提问作者syv

