09 | 调优一筹莫展,配置项速查手册让你事半功倍!(上)
配置项的分类
- 深入了解
- 翻译
- 解释
- 总结
本文是一篇关于Spark性能调优配置项的速查手册。作者通过对Spark配置项的分类,分别介绍了与硬件资源、Shuffle操作和Spark SQL相关的配置项。在硬件资源类中,作者详细介绍了与CPU和内存设置相关的配置项,包括spark.cores.max、spark.executor.cores、spark.task.cpus、spark.default.parallelism、spark.sql.shuffle.partitions等参数。对于CPU设置,作者强调了并行度和并行计算任务的关系,以及它们对数据粒度和内存消耗的影响。在内存设置方面,作者介绍了堆内内存和堆外内存的管理模式,以及相应的配置项含义和设置方法。文章还讨论了User Memory的分配和作用,以及如何根据应用中的自定义数据结构来调整内存区域的相对占比。总的来说,本文通过对Spark配置项的分类和详细介绍,为读者提供了快速了解和使用Spark性能调优配置项的指南。文章内容涵盖了硬件资源、内存管理和数据结构存储等方面,对于需要进行Spark性能调优的读者来说,是一份非常有价值的参考资料。文章还提到了与磁盘设置有关的配置项spark.local.dir,以及如何平衡Execution Memory与Storage Memory。同时,作者还提出了每日一练的问题,引导读者深入思考和学习。整体而言,本文内容丰富,涵盖了多个方面的Spark性能调优配置,对读者进行快速了解和深入学习都具有很高的参考价值。
《Spark 性能调优实战》,新⼈⾸单¥59
全部留言(30)
- 最新
- 精选
- Joe老师,针对spark.sql.shuffle.partitions的使用有一些疑问? 1. 如果df1.join(df2),df1用的是hash partitioner并且分区数是3,这种情况在reduce端参数spark.sql.shuffle.partitions会生效吗?还是以df1的分区为准? 2. 这个参数是针对所有的Dataframe,DataSet和SQL,还是只有SQL生效?
作者回复: 先来回答第二个问题,这个参数对所有的DF、DS、SQL都生效。 再来说第一个问题,例子蛮好的。先说答案,然后咱们再去分析:对于你这种情况,两张表都会Shuffle。当然,假设你的表都很大,超过广播阈值,能转换成Broadcast join那就另当别论了。 为什么呢?spark.sql.shuffle.partitions默认是200。 这部分其实需要一些“前置引用”的知识,这些知识其实是在22讲Physical Planning才会涉及,所以在这一讲这里会比较难理解。 是这样的,Spark SQL执行计划中的每一个节点,都有4个重要的属性,分别是: 节点要求的输入: 1)requiredChildDistribution 2)requiredChildOrdering 节点的输出: 3)outputPartitioning 4)outputOrdering 每个节点都有输出的分区情况、排序情况,也就是3)、4);同时,每个节点对于自己的子节点,都有关于 分区和排序的要求,也就是1)、2)。 当子节点的分区与排序情况,不满足当前节点的输入要求时,Spark SQL就会在Physical planning阶段,强行插入一些中间节点,比如Exchange(Shuffle)。 回到你的问题,join要求子节点(df1、df2)的outputPartitioning是以joinKey为分区键,分成200个分区(因为spark.sql.shuffle.partitions默认值是200)。但是,你的df1,有3个分区;df2未知,因此,Spark SQL会在物理计划阶段给两个子节点,也就是df1、df2强行插入Exchange、也就是Shuffle。这两个Shuffle,会分别把df1、df2变成是有200个分区的分布式数据集。两个Shuffle做完之后,才会计算后面的Join。 所以,最终的分区,不是df1的3、也不是df2原来的分区,而是spark.sql.shuffle.partitions参数设定的值。
2021-04-2939 - 斯盖丸关于spark.sql.shuffle.partitions 老师实际工作中我发现这个参数不管用。比如我把它设成2000,并去读parquet文件,大约几百个文件吧,但我看task数量只有80个,而且还一直在变,有时会更少。网上说spark-sql的并行度不管用,要自己手动repartition,是这样吗?task数量一直在变是因为不断地在做groupBy和join吗?那为什么task数量始终达不到我设的spark.sql.shuffle.partitions = 2000呢?
作者回复: 这块确实有点坑,只有你的计算中涉及Joins或是聚合,spark.sql.shuffle.partitions,这个参数的设置,才会影响Shuffle Reduce阶段的并行度。如果你的作业没有Joins或是聚合计算,那确实,这个参数设了也是摆设。 比如你仅仅是读Parquet,然后想通过这个参数调整并行度,确实是徒劳,这个时候,你确实只能自己用repartition或是Coalesce去做重分区。
2021-04-16518 - 断笔画墨spark读取oracle表,oracle表结构没有数值类型,大部分都是varchar,数据量上亿,怎么在源端做高并发读取啊
作者回复: 我理解数据读取效率和字段类型没什么关系,要提高并行计算效率,可以考虑使用API: spark.read.jdbc(url, table, predicates, props) 其中url就是你的Oracle DB table是表名 props是各种属性,比如权限信息,如user,password predicates比较关键,是划分数据分区的谓词数组,比如["id between 1 and 100", "id between 101 and 200", ... "id between 901 and 1000"],本质上就是用这些过滤条件把查询分成多个,每个查询的结果都是一个数据分片。这么做的好处,是可以提高Spark的并行度,但是要注意,同时发这么多查询请求给Oracle,要注意Oracle数据库本身的并发处理能力。
2021-04-24314 - Geek_d794f8Spark.task.cpus这个参数的设置,我之前理解就是一个cpu核运行一个task。难道还可以0.5个cpu或者多个cpu运行一个task吗?
作者回复: 好问题,通常来说,这个参数都不需要动,默认就是1。回答你的问题,这个值,不能小于1。那么大于1是什么情况呢?就是你的task本身,是需要多线程操作的,比如一个线程把数据写到HDFS,另外一个线程,通过JDBC同时把数据塞进DBMS,诸如此类。 Spark.task.cpus这个参数的意思,在于Spark为这种特殊的多线程task提供了一种开放的可能,允许你去设置大于1的cpu core。但允许不代表你一定要这么做哈 特别注意的是,如果你的task没什么特别,但你还是设置的大于1的数值,那cpu就是白白浪费。spark只会去同时launch (spark.executor.cores / spark.task.cpus)这么多的tasks。
2021-04-1512 - 快跑Class Student是存在User Memory? new Student("小明")是存在Executor Memory?
作者回复: 这个其实取决于你把对象放在哪里。 分两种情况来看哈~ 1. 如果你用RDD封装这些自定义类型,比如RDD[Student],那么,数据集消耗的是Execution memory。 2. 相反,如果你是在处理分布式数据集的函数中,new Student来辅助计算过程,那么这个对象,是放在User memory里面的。
2021-04-13311 - Geek_d794f8老师是不是可以这样理解,spark-submit提交任务的时候申请的总cores数为10,yarn调度系统会分配10个v-core,如果集群资源充足,实际上一个v-core就是对应一个cpu核,如果资源不够,相当于就不是一对一,此时集群最大的task并行度并不是10,而是并发度为10。 以上理解对吗?
作者回复: 并行度和并发度是两个完全不同的概念,一个数据视角——并行度;一个是计算视角——并发度,这个我们本讲应该有过介绍哈~ 另外你说的spark.executor.cores与v-core的对应关系是没问题的。但是cores也好,v-core也罢,物理上不见得对应的是一个物理CPU core,这个要看CPU的硬件配置,有些CPU只能起一个线程,不过大部分现代CPU都能起两个线程。所以spark.executor.cores与v-core,更准确的对应,是线程,而不是物理上的CPU core。这个地方其实有点绕,需要注意。
2021-04-157 - 快跑一个任务报错Container Killed by Yarn For Exceeding Memory Limits Consider boosting spark.yarn.executor.memoryOverhead 我按照提示增加spark.yarn.executor.memoryOverhead,任务的确执行通过。 请教老师spark.yarn.executor.memoryOverhead参数控制哪部分内存,主要负责什么?什么情况下会用到这部分内存。文章中关于内存的好像没有提到这部分。
作者回复: spark.executor.memoryOverhead ,在yarn、k8s部署模式下,container会预留一部分内存,形式是堆外,用来保证稳定性,主要存储nio buffer,函数栈等一些开销,所以你看名字:over head。这部分内存,他的目的是保持Spark作业运行时的稳定性。 这个failure,报这个错,说明overhead空间不足,系统必须的开销没有足够的空间~ 调大就行了~ 这部分内存和执行性能关系不大,所以咱们课程里没有提。
2021-04-1936 - 辰老师,这个自定义结构不是很懂,什么样的数据格式是自定义数据格式,我现在经常接触到的是spark-submit 提交sparksql这一块,用的是hive表,这个涉及自定义数据结构吗
作者回复: 好问题,你可以这么来理解,凡是数据源,不管是Hive来的,还是HDFS来的,还是S3来的,不管是什么格式,比如Parquet、ORC,这些数据源,consume的都是执行内存,当然,如果他们被cache了,那就消耗Storage memory。 那些开发者自己自定义的类、类型、数据结构、Struct,等等,这些东西往往用来辅助完成对于刚刚说的那些数据源的处理,这些辅助性的类、类型、数据结构、Struct,才是自定义数据结构。他们消耗的,就是user memory。
2021-04-125 - Sean根据老师的回回复,个人总结如下,不知是否正确:在不使用yarn,k8s模式下,完全没有必要启用off heap,而且在钨丝计划的加持下,可以理解为使用堆内内存,不会对任务有任何影响,但在使用yarn或k8s模式下,必须要开启off heap,否则会出现t Container Killed by Yarn For Exceeding Memory Limits Consider boosting spark.yarn.executor.memoryOverhead报错,需要调大spark.yarn.executor.memoryOverhead
作者回复: 对的,总结的很到位~
2021-08-2234 - 西南偏北并行度太高可能会造成任务调度耗时超过任务处理耗时,如果不进行后续分区合并,还有会造成小文件问题(比如写入Hive)
作者回复: 满分💯
2021-05-044