spark 分区 提交 调优

转自:https://blog.csdn.net/u014384314/article/details/80797385

一 spark RDD分区原则

在Spark的Rdd中,Rdd默认是分区的。

有时候需要重新设置Rdd的分区数量,比如Rdd的分区中,Rdd分区比较多,但是每个Rdd的数据量比较小,则需要重新设置一个比较合理的分区数。或者需要把Rdd的分区数量调大。还有就是通过设置一个Rdd的分区来达到设置生成的文件的数量。

 

二.coalesce和repartition   partitionby(后面一点说)

有两种方法是可以重设Rdd的分区:分别是 coalesce()方法和repartition()。

1.后者是前者的特殊情况,即原有分区如果为4,若 .repartition(8) <=> .coalesce(8,true) 就会将原有分区数改为8 ,一般用于将原有分区数扩大。shuffle=true ,表示必须进行洗牌操作(该操作需要占用一定的时间,shuffle操作可以增加park程序的并行度),才能增大分区。如果coalesce(8) <=>coalesce(8,false) 则该方法不起作用,分区数仍为4

2. 如果需要将原有分区N减小到M个分区,则只能用coalesce,且分两种情况:

如果N>M并且N和M相差不多,(假如N是1000,M是100)那么就可以将N个分区中的若干个分区合并成一个新的分区,最终合并为M个分区,这时可以将shuffle设置为false(以节约运行时间)

如果N>M并且两者相差悬殊,这时如果将shuffle设置为false,父子RDD是窄依赖关系,他们同处在一个Stage中,就可能造成spark程序的并行度不够,从而影响性能,如果在M为1的时候,为了使coalesce之前的操作有更好的并行度,可以将shuffle设置为true。

 

三. 关于宽依赖和窄依赖

窄依赖是指父Rdd的分区最多只能被一个子Rdd的分区所引用,即一个父Rdd的分区对应一个子Rdd的分区,或者多个父Rdd的分区对应一个子Rdd的分区。

其中map操作 就是窄依赖,窄依赖是懒加载的,不进行shuffle,不会立即执行。

而宽依赖就是宽依赖是指子RDD的分区依赖于父RDD的多个分区或所有分区,即存在一个父RDD的一个分区对应一个子RDD的多个分区。1个父RDD分区对应多个子RDD分区,这其中又分两种情况:1个父RDD对应所有子RDD分区(未经协同划分的Join)或者1个父RDD对应非全部的多个RDD分区(如groupByKey)。 join  需要针对同一个 key 合并,所以需要 shuffle

窄依赖跟宽依赖的区别是是否发生 shuffle(洗牌) 操作.宽依赖会发生 shuffle 操作. 窄依赖是子 RDD的各个分片(partition)不依赖于其他分片,能够独立计算得到结果,宽依赖指子 RDD 的各个分片会依赖于父RDD 的多个分片,所以会造成父 RDD 的各个分片在集群中重新分片, 看如下两个示例:

// Map: "cat" -> c, cat

val rdd1 = rdd.Map(x => (x.charAt(0), x))

// groupby same key and count

val rdd2 = rdd1.groupBy(x => x._1).

Map(x => (x._1, x._2.toList.length))

  第一个 Map 操作将 RDD 里的各个元素进行映射, RDD 的各个数据元素之间不存在依赖,可以在集群的各个内存中独立计算,也就是并行化,第二个 groupby 之后的 Map 操作,为了计算相同 key 下的元素个数,需要把相同 key 的元素聚集到同一个 partition 下,所以造成了数据在内存中的重新分布,即 shuffle 操作.shuffle 操作是 spark 中最耗时的操作,应尽量避免不必要的 shuffle. 

spark shuffle本质:根据分区分组、join等算子的条件key(groupbykey,partitionBy key,join by key,repartition(n),coalesce(n,true)) 将处于多个分区的数据拉取出来,重新放到给定的一个或者多个分区下。

 

四. RDD

 RDD 的创建方式主要有2种: 

- 并行化(Parallelizing)一个已经存在与驱动程序(Driver Program)中的集合如set、list; 

- 读取外部存储系统上的一个数据集,比如HDFS、Hive、HBase,或者任何提供了Hadoop InputFormat的数据源.也可以从本地读取 txt、csv 等数据集

 RDD 的操作函数(operation)主要分为2种类型 Transformation 和 Action.

类别    函数    区别
Transformation    Map,filter,groupBy,join, union,reduce,sort,partitionBy    返回值还是 RDD,不会马上 提交 Spark 集群运行
Action    count,collect,take,save, show    返回值不是 RDD,会形成 DAG 图,提交 Spark 集群运行 并立即返回结果
Transformation 操作不是马上提交 Spark 集群执行的,Spark 在遇到 Transformation 操作时只会记录需要这样的操作,并不会去执行,需要等到有 Action 操作的时候才会真正启动计算过程进行计算.针对每个 Action,Spark 会生成一个 Job, 从数据的创建开始,经过 Transformation, 结尾是 Action 操作.这些操作对应形成一个有向无环图(DAG),形成 DAG 的先决条件是最后的函数操作是一个Action.

 

五.spark2.x  shuffle

bucket的数量=cpu*resultTask的个数

版本二设计的原理:一个shuffleMapTask还是会写入resultTask对应个数的本地文件,但是当下一个shuffleMapTask运行的时候会直接把数据写到之前已经建立好的本地文件,这个文件可以复用,这种复用机制叫做consolidation机制

我们把这一组的shuffle文件称为shuffleGroup,每个文件中都存储了很多shuffleMapTask对应的数据,这个文件叫做segment,这个时候因为不同的shuffleMapTask都是存在一个文件中

所以建立索引文件,来标记shuffleMapTask在shuffleBlockFile的位置+偏移量,这样就可以在一个文件里面把不同的shuffleMaptask数据分出来

 

六. coalesce(n,true),repartition() 与 partitionby() 

都是对数据进行重新分区,分区算法默认都是使用 HashPartitioner

 

七.  DF的几种save Table 方式的比较:

7.1 df.write.mode(SaveMode.Append).saveAsTable("testDB.testTableName")  

可以直接将df 保存在一个新的hive表中(不分区不需要事先在hive用语句建表),df中有多少分区,hive中就有多少分区,没有分区key

7.2 df.repartition(n).write.mode(SaveMode.Append).saveAsTable("testDB.testTableName") 

df.repartition(n).write.mode(SaveMode.Overwrite ).saveAsTable("testDB.testTableName") 可以直接将df 保存在一个新的hive表中(因为这种方式的RDD的分区的key是随机生成的,所以保存到hive表中时并不会真正分区,所以也不需要事先在hive用语句建表),且 对df 重新分区,分区数为n,各个分区的key 随机生成。

注意:SaveMode.Overwrite 写入模式:不支持partitionby即

df.write.mode(SaveMode.Overwrite).partitionby("year","month","day").saveAsTable("testDB.testTableName") 会报错,即使事先在hive用语句建了分区表也不行,因为Overwrite 会先删除hive分区表,再重新建表,重新建表的时候不能自动建分区表,就会报错

7.3 df.repartition(n).write.mode(SaveMode.Append).partitionby("year","month","day").saveAsTable("testDB.testTableName") 

可以将df 保存在一个新的hive表中(但是需要事先在hive用语句建分区表,根据partitionby的参数分区,为什么要这样做呢?DATAFRAM.SaveTestRead创建RDD分区,而不是HiVE分区。解决方法是在调用DataFrame.saveAsTable之前通过HQL创建表。),该语句会 对df 重新分区,分区数为n,各个分区的key 随机生成,然后再按年月日分区。即 把df 的数据 先按HashPartitioner算法 ,分布在n个分区中,再对每一个分区 按年月日分为 更小的分区。

7.4  df.write.mode(SaveMode.Append).partitionby("year","month","day").saveAsTable("testDB.testTableName") 

可以将df 保存在一个新的hive表中(但是需要事先在hive用语句建分区表,根据partitionby的参数分区) 。即把df 的数据 按HashPartitioner算法  按年月日分为 更小的分区。df中有多少天的数据就有多少个分区。

对7.1 到7.4 为什么不用 coalesce(n)?因为 在spark1.6中coalesce(n) 默认shuffle=false用于调小分区数,而我们并不是很清楚df 本身的分区数,所以除了将n设为1,其他都有可能将分区调大,而coalesce(n) 方法是不能调大分区数的,因为他不能进行shuffle操作。当然如果你清楚了df的分区数,且希望调小分区,你最好是采用coalesce(n),因为它不需要进行shuffle操作,所以save操作耗时更短。

7.3 与7.4 的比较: 1. 前者最终的分区数>=后者的分区数,一般情况下 大于,特殊情况等于,因为分区数越多,存储的并行度越高,所以save操作耗时更短。相反根据年月日拉取save后的结果表后者会更快,因为后者同一天的数据都在一个分区中,而前者可能在多个分区中。

总结:

为什么要重新分区再 保存结果?

想避免小文件。如果不重新分区的话,SparkSQL DataFrame保存到hdfs时出现过多小文件问题。

因为多线程并行往hdfs写造成的(因为每个DataFrame/RDD分成若干个Partition,这些partition可以被并行处理)。

其结果就是一个存下来的文件,其实是hdfs中一个目录,在这个目录下才是众多partition对应的文件,最坏的情况是出现好多size为0的文件。

save Table 效率排名(分区数越多,效率越高,速度越快 ):

在n<天数的情况下 7.3>7.4>7.2 和7.1

效率:repartition(1)>repartition(5)>repartition(10)

           coalesce(1)>coalesce(2)>coalesce(5)

           coalesce>repartition

  读取save后表的效率:分区数越多,执行线程并行度越高,效率越高,速度越快 

 

最佳实践:

sqlhiveContext.sql("set hive.exec.dynamic.partition.mode=nonstrict")

sqlhiveContext.sql("set hive.exec.dynamic.partition=true")

//按下面方法save可以避免本次执行出现小文件过多的情况:

df.coalesce(1).write.mode(SaveMode.Append).partitionby("year","month","day").saveAsTable("testDB.testTableName")

df.repartition(1).write.mode(SaveMode.Append).partitionby("year","month","day").saveAsTable("testDB.testTableName")

注意:虽然可以使本次执行避免出现小文件过多,但是如果执行的次数很多,每次结果的数据量也不大,也会出现文件过多的情况,这时需要定时对历史所有结果重新执行
df.coalesce(1).write.mode(SaveMode.Append).partitionby("year","month","day").saveAsTable("testDB.testTableName")

并删除原来的小文件集。

解析:先将df 的小文件合并(一般df都是某个逻辑之后的结果,肯定有很多分区内的小文件),合并为1个分区能最大限度的合并小文件,spark1.6中用 coalesce(1)而不用repartition(1)的原因是,前者不需要进行shuffle操作,节约运行时间,最后再将这一个分区 按年月日 分为 多个小的分区,有多少天 就有多少个分区。(注意:需要事先在hive用语句建分区表,根据partitionby的参数分区;因为这里的分区只是RDD的分区,而不能设置hive分区) 。 最后为什么要按年月日分区呢,一方面把分区数从1再次增大,RDD分区数越多 ,可以提高程序运行(save)的并行度;另一方面 保存到分区表之后,再通过年月日 来筛选过滤数据,以进行某些查询(逻辑),会大大提高效率,因为同一天的数据放在同一分区,同一分区的数据 在物理地址上相邻(基本保持顺序存储),查询速度会更快。

为什么会产生小文件?
因为spark 的.saveAsTable("test_yw.testX") 写数据到hdfs时,有多少个reduce,就会有多少个小文件,reduce是并行写数据到各个文件,这也是spark 写速度快,但是容易产生小文件的原因。

而mapReduce的 map之后溢出的文件会从不同的节点 最终被拉取到一个地方(节点)进行合并,合并为1个文件,然后再进行reduce 。这也是spark 与mapreduce 的区别之一。

例子:
val df = sqlHiveContext.createDataFrame(Seq((1, 2017, 11, 13, "zhangsan", 21), (0, 2018, 11, 14, "lisi", 18), (0, 2017, 11, 14, "lisi1", 18), (1, 2018, 11, 14, "lisi", 18), (0, 2017, 11, 14, "lisi", 18), (0, 2017, 11, 14, "lisi", 18)))

.toDF("a", "b", "c", "d", "e", "f")

df.cache()

df.show(false)

df.write.mode(SaveMode.Overwrite).partitionBy("b").saveAsTable("test_yw.testX")

df.repartition(1).write.mode(SaveMode.Overwrite).partitionBy("b").saveAsTable("test_yw.testX1")

执行后查看hdfs文件,结果如下:

+---+----+---+---+--------+---+
|a  |b   |c  |d  |e       |f  |
+---+----+---+---+--------+---+
|1  |2017|11 |13 |zhangsan|21 |
|0  |2018|11 |14 |lisi    |18 |
|0  |2017|11 |14 |lisi1   |18 |
|1  |2018|11 |14 |lisi    |18 |
|0  |2017|11 |14 |lisi    |18 |
|0  |2017|11 |14 |lisi    |18 |
+---+----+---+---+--------+---+
没有repartition(1),但是partitionBy("b"),b=2017的有4条记录,其在b=2017的分区中也有4个文件,b=2018的行有两条记录,其在b=2018的分区中也有两个文件。

 
[greesj2b@slave8 ~]$ hdfs dfs -ls /user/hive/warehouse/test_yw.db/testx
Found 5 items
-rw-r--r--   3 260169 supergroup          0 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/_SUCCESS
-rw-r--r--   3 260169 supergroup        514 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/_common_metadata
-rw-r--r--   3 260169 supergroup       3956 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/_metadata
drwxr-xr-x   - 260169 supergroup          0 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/b=2017
drwxr-xr-x   - 260169 supergroup          0 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/b=2018
 
[greesj2b@slave8 ~]$ hdfs dfs -ls /user/hive/warehouse/test_yw.db/testx/b=2017
Found 4 items
-rw-r--r--   3 260169 supergroup       1070 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/b=2017/part-r-00014-b33e1370-34d1-4913-85c9-17f127669c4e.gz.parquet
-rw-r--r--   3 260169 supergroup       1055 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/b=2017/part-r-00044-b33e1370-34d1-4913-85c9-17f127669c4e.gz.parquet
-rw-r--r--   3 260169 supergroup       1050 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/b=2017/part-r-00074-b33e1370-34d1-4913-85c9-17f127669c4e.gz.parquet
-rw-r--r--   3 260169 supergroup       1050 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/b=2017/part-r-00089-b33e1370-34d1-4913-85c9-17f127669c4e.gz.parquet
[greesj2b@slave8 ~]$ hdfs dfs -ls /user/hive/warehouse/test_yw.db/testx/b=2018
Found 2 items
-rw-r--r--   3 260169 supergroup       1050 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/b=2018/part-r-00029-b33e1370-34d1-4913-85c9-17f127669c4e.gz.parquet
-rw-r--r--   3 260169 supergroup       1050 2018-10-11 13:57 /user/hive/warehouse/test_yw.db/testx/b=2018/part-r-00059-b33e1370-34d1-4913-85c9-17f127669c4e.gz.parquet
既repartition(1),又partitionBy("b")每个分区各只有一个小文件

[greesj2b@slave8 ~]$ hdfs dfs -ls /user/hive/warehouse/test_yw.db/testx1
Found 5 items
-rw-r--r--   3 260169 supergroup          0 2018-10-11 14:00 /user/hive/warehouse/test_yw.db/testx1/_SUCCESS
-rw-r--r--   3 260169 supergroup        514 2018-10-11 14:00 /user/hive/warehouse/test_yw.db/testx1/_common_metadata
-rw-r--r--   3 260169 supergroup       1671 2018-10-11 14:00 /user/hive/warehouse/test_yw.db/testx1/_metadata
drwxr-xr-x   - 260169 supergroup          0 2018-10-11 14:00 /user/hive/warehouse/test_yw.db/testx1/b=2017
drwxr-xr-x   - 260169 supergroup          0 2018-10-11 14:00 /user/hive/warehouse/test_yw.db/testx1/b=2018
[greesj2b@slave8 ~]$ hdfs dfs -ls /user/hive/warehouse/test_yw.db/testx1/b=2017
Found 1 items
-rw-r--r--   3 260169 supergroup       1270 2018-10-11 14:00 /user/hive/warehouse/test_yw.db/testx1/b=2017/part-r-00000-1d0246a7-da71-4a2c-af26-053ef3b4f176.gz.parquet
[greesj2b@slave8 ~]$ hdfs dfs -ls /user/hive/warehouse/test_yw.db/testx1/b=2018
Found 1 items
-rw-r--r--   3 260169 supergroup       1205 2018-10-11 14:00 /user/hive/warehouse/test_yw.db/testx1/b=2018/part-r-00000-1d0246a7-da71-4a2c-af26-053ef3b4f176.gz.parquet
再执行一次df.repartition(1).write.mode(SaveMode.Overwrite).partitionBy("b").saveAsTable("test_yw.testX1"),会发生什么?

每个分区都新增了1个文件,这也验证了:虽然可以使本次执行避免出现小文件过多,但是如果执行的次数很多,每次结果的数据量也不大,也会出现文件过多的情况,这时需要定时对历史所有结果重新执行repartiton(1),partitionBy("b")

[greesj2b@slave8 ~]$ hdfs dfs -ls /user/hive/warehouse/test_yw.db/testx1/b=2018
Found 2 items
-rw-r--r--   3 260169 supergroup       1205 2018-10-11 14:00 /user/hive/warehouse/test_yw.db/testx1/b=2018/part-r-00000-1d0246a7-da71-4a2c-af26-053ef3b4f176.gz.parquet
-rw-r--r--   3 260169 supergroup       1205 2018-10-11 14:31 /user/hive/warehouse/test_yw.db/testx1/b=2018/part-r-00000-3661f709-97c7-4c0d-a357-e610af7ba2a1.gz.parquet
[greesj2b@slave8 ~]$ hdfs dfs -ls /user/hive/warehouse/test_yw.db/testx1/b=2017
Found 2 items
-rw-r--r--   3 260169 supergroup       1270 2018-10-11 14:00 /user/hive/warehouse/test_yw.db/testx1/b=2017/part-r-00000-1d0246a7-da71-4a2c-af26-053ef3b4f176.gz.parquet
-rw-r--r--   3 260169 supergroup       1270 2018-10-11 14:31 /user/hive/warehouse/test_yw.db/testx1/b=2017/part-r-00000-3661f709-97c7-4c0d-a357-e610af7ba2a1.gz.parquet
[greesj2b@slave8 ~]$ 
既无repartition(1),又无partitionBy("b")

df.write.mode(SaveMode.Append).saveAsTable("test_yw.testX2") (有91个小文件)

Found 91 items
-rw-r--r--   3 260169 supergroup          0 2018-10-11 14:15 /user/hive/warehouse/test_yw.db/testx2/_SUCCESS
-rw-r--r--   3 260169 supergroup        582 2018-10-11 14:15 /user/hive/warehouse/test_yw.db/testx2/part-r-00000-ca1d1b08-798b-4e3f-a5f4-3d1bbaa45266.gz.parquet
-rw-r--r--   3 260169 supergroup        582 2018-10-11 14:15 /user/hive/warehouse/test_yw.db/testx2/part-r-00001-ca1d1b08-798b-4e3f-a5f4-3d1bbaa45266.gz.parquet
-rw-r--r--   3 260169 supergroup        582 2018-10-11 14:15 /user/hive/warehouse/test_yw.db/testx2/part-r-00002-ca1d1b08-798b-4e3f-a5f4-3d1bbaa45266.gz.parquet
-rw-r--r--   3 260169 supergroup        582 2018-10-11 14:15 /user/hive/warehouse/test_yw.db/testx2/part-r-00003-ca1d1b08-798b-4e3f-a5f4-3d1bbaa45266.gz.parquet
-rw-r--r--   3 260169 supergroup        582 2018-10-11 14:15 /user/hive/warehouse/test_yw.db/testx2/part-r-00004-ca1d1b08-798b-4e3f-a5f4-3d1bbaa45266.gz.parquet
-rw-r--r--   3 260169 supergroup        582 2018-10-11 14:15 /user/hive/warehouse/test_yw.db/testx2/part-r-00005-ca1d1b08-798b-4e3f-a5f4-3d1bbaa45266.gz.parquet
八.Spark的并行度指的是什么?

  1.  spark作业中,各个stage的task的数量,也就代表了spark作业在各个阶段stage的并行度!

    当分配完所能分配的最大资源了,然后对应资源去调节程序的并行度,如果并行度没有与资源相匹配,那么导致你分配下去的资源都浪费掉了。同时并行运行,还可以让每个task要处理的数量变少(很简单的原理。合理设置并行度,可以充分利用集群资源,减少每个task处理数据量,而增加性能加快运行速度。)

2、如何设置一个Spark Application的并行度?

      spark.defalut.parallelism 默认是没有值的,如果设置了值比如说10,是在shuffle的过程才会起作用(val rdd2 = rdd1.reduceByKey(_+_) //rdd2的分区数就是10,rdd1的分区数不受这个参数的影响)

  // 如果提交脚本中设置了20个executor ,每个executor 有4个core,那么就设置成20*4 的2到3倍    

  new SparkConf().set("spark.defalut.parallelism",''160'')//

.set("spark.executor.memory",''15g'')

九. spark 提交语句
1. 提交参数的设置既可以在提交脚本里面设置,也可以在spark 程序里面设

xx.sh

spark-submit --master yarn-client --class com.gree.test.Test --driver-memory 4g --num-executors 20 --executor-cores 4 --executor-memory 15g --driver-java-options '-Xms5g -Xmx5g -XX:+UseCompressedOops' --conf spark.driver.maxResultSize=2g --conf spark.executor.heartbeatInterval=15s --conf spark.yarn.executor.memoryOverhead=3072 --conf spark.memory.useLegacyMode=true --conf spark.shuff le.memoryFraction=0.5 --conf spark.storage.memoryFraction=0.3 --conf "spark.executor.extraJavaOptions=-XX:+UseG1GC -xx:InitiatingHeapOccupancyPercent=25 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps" --queue production/home/..../mysubmit/xxx.jar

提交参数说明:

./bin/spark-submit \

--class <main-class>

--master <master-url> \

--deploy-mode <deploy-mode> \

--conf <key>=<value> \

... # other options

<application-jar> \

[application-arguments]

--class: The entry point for your application (e.g. org.apache.spark.examples.SparkPi)
--master: The master URL for the cluster (e.g. spark://23.195.26.187:7077)
--deploy-mode: Whether to deploy your driver on the worker nodes (cluster) or locally as an external client (client) (default: client) †
--conf: Arbitrary Spark configuration property in key=value format. For values that contain spaces wrap “key=value” in quotes (as shown).
application-jar: Path to a bundled jar including your application and all dependencies. The URL must be globally visible inside of your cluster, for instance, an hdfs:// path or a file:// path that is present on all nodes.
application-arguments: Arguments passed to the main method of your main class, if any
详见:https://blog.csdn.net/stardhb/article/details/50454680

在spark scala 里面设置:

val conf =new SparkConf().setAppName("testProject").setMaster("yarn-client")

//.setMaster("spark://bakmaster:7077")//standalong

//.setMaster("local[*]")

//.setMaster("local[6]")

//.setMaster("local")

//.setMaster("yarn-cluster")//集群的客户端模式

//.setMaster("mesos://HOST:5050")//集群模式

// mysql配置

conf.set("spark.driver.extraClassPath","/opt/cm-5.7.1/share/cmf/lib/mysql-connector-java-5.1.33-bin.jar")

conf.set("spark.executor.extraClassPath","/opt/cm-5.7.1/share/cmf/lib/mysql-connector-java-5.1.33-bin.jar")

// sqlserver配置

conf.set("spark.driver.extraClassPath","/opt/cloudera-manager/cm-5.7.1/share/cmf/lib/sqljdbc4.jar")

conf.set("spark.executor.extraClassPath","/opt/cloudera-manager/cm-5.7.1/share/cmf/lib/sqljdbc4.jar")

// oracle 配置

conf.set("spark.driver.extraClassPath","/opt/cloudera-manager/cm-5.7.1/share/cmf/lib/ojdbc6.jar")

conf.set("spark.executor.extraClassPath","/opt/cloudera-manager/cm-5.7.1/share/cmf/lib/ojdbc6.jar")

// 提交参数的配置

/*conf.set("spark.locality.wait.process","300s")

conf.set("spark.locality.wait.node","200s")

 

conf.set("spark.default.parallelism","300")

conf.set("spark.executor.memory","20g")

 

conf.set("spark.cores.max","100")

*/ 

 

2.提交参数的配置生效的优先级:

conf.set("key","value")> spark-submit>spark-defaults.conf 

 

spark 调优 参考:

https://blog.csdn.net/vinfly_li/article/details/79415342
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值