Spark重点总结

简介

  Spark和MapReduce的功能差不多,主要做分布式计算的,而分布式存储还是由HDFS来做,其中Spark进行数据转换时最核心的概念就是RDD,既然是做分布式计算的,那就要搞懂

  • Spark是怎么进行分布式计算的以及工作流程
  • Spark各个模块解决的问题以及特点
  • Spark RDD中API的使用场景

  上面说了,spark进行分布式计算是基于HDFS的,所以不光要启动spark集群,还是要启动HDFS集群

//hdfs
start-dfs.sh

//spark
sh ~/bigdata/spark-2.2.0-bin-hadoop2.7/sbin/start-all.sh


//进入spark交互命令行
spark-shell --master spark://master:7077

   查看一些spark任务的运行状态,可以到监控界面上查看http://master:8080/,监控界面更多详细信息阶段:戳这

 

重点

  1. RDD的特点
  2. RDD的Transformation API和Action API
  3. Spark依赖设计
  4. Spark的分区器
  5. Spark中stage划分
  6. 提交spark任务的运行模式以及Spark Job提交流程
  7. 延迟调度和动态资源管理
  8. Shuffle性能提升
  9. Api详细

 

1.RDD的特点

  RDD是一个只读且分区的数据集

  1. 分区并行计算
  2. RDD分区计算都有自己的计算函数
  3. 维持RDD依赖列表,通过这个依赖列表进行容错
  4. 可以按照一定规则自行分区,这些在RDD分区元数据信息有体现
  5. 分区数据有机器存储地址,根据地址到对应的机器上计算,以实现计算任务的本地性
  6. spark的计算是流式计算,就是取一条计算一条,主要就是用Iterator来实现的

  具体的RDD都会实现抽象接口中的这几个方法

  1. compute  计算分区的数据得到一个Iterator结果
  2. getPartitions   获取RDD的分区列表,用于并行计算
  3. getDependencies  获取依赖列表
  4. getPreferredLocations  获取分区数据存储在哪些机器上等位置信息,用于本地性计算
  5. partitioner 分区器,默认是没有指定的,可以自行指定分区器

 

2.TopN的实现:

  单个TopN的实现:(1)两次mapPartition,第一次各个分区求TopN,第二次重分区为一个分区后,求这个分区的TopN  (2)一次mapPartition + PriorityQueue,PriorityQueue这个东西,从翻译上看,就是优先级队列,它里面是用二叉堆实现的,这种数据结构有个特点,就是默认情况下,第一个 数是最小的,这个特点在维持topn数据用于判断新元素是否进队列;第一个mapPartition就是各分区维护一个TopN优先级队列,最后再把各个队列汇总到一个队列中   (3)使用 RDD的top接口,这个本质上就是用的第二种 方式

 

3.Spark SQL中,API演化的合理性

  在Spark SQL操作中,它支持SQL、DataFrame、DataSet三种数据类型的操作方式,那它们有什么区别呢,那这个就要从错误检查角度来说明了,在执行SQL语句时,常见有语法错误和解析错误 两种错误,语法错误你就理解为,比如关键词select写错,而解析错误则是,比如表字段写错,对于这两种错误,如果是SQL字符串,那么都只在运行时才会发现,DataFrame由于提供DSL API,但是它不是强制类型,所以语法错误能在编译时发现,但发现不了解析错误,而DataSet是强制类型,所以这两种错误都能在编译时发现

 

 Spark SQL重点总结:

  1. DataFrame和DataSet的创建

  DataFrame的创建 主要有5种方式:前四种调用createDataFrame,可传入RDD[Product子类],Seq[Product子类],RDD[Java类]+classOf[Java类],RDD[Row]+schema,其中 case class和tuple都是Product子类,第五种方式就是读文件接口,默认就是DataFrame数据类型,比如read.json

  DataSet的创建 主要有3种方式:第一种是spark.range默认返回的就是DataSet数据类型,另外两种调用createDataset,可传类型Seq[T]和RDD[T],由于JVM对象类型与spark SQL内部数据类型需要转换,在创建DataSet时,需要通过柯里化的形式传入Encoders,它就是负责这个转换动作的,那么这个柯里化参数是一个隐式参数,对于T如果是常用的数据类型就可以不用传,那么通过隐式转换import spark.implicits._ 就可以,而对于自定义的类(比如Java类),需要自己通过柯里化的方式传入Encoders.bean(classOf[类])

  RDD和DF和DS三者互转 : 1.转RDD -> 两种数据类型调用.rdd  2.转DF -> rdd和ds都是调用.toDF  3.转DS -> rdd.toDS和df.as[类型],三种数据结构的特点比较:RDD和DS都是强类型数据结构,而DF和DS都有schema信息(表头等信息),所以在由其他转成DF数据,数据类型丢失,所以DF转DS需要给定类型,而DF转RDD,则是默认成Row类型,而不是原来类型,另外由其他转成RDD,schema信息会丢失,但是RDD转成这两种数据不用传schema,是因为会根据RDD的特点创建默认的schema,rdd调用转换方法时,需要隐式转换  其他注意的

 

  2.Spark SQL支持的外部数据源

  Spark SQL内置支持的数据源就有parquet,orc,json,csv,text,jdbc,table(hive) 代码详情

  在未指定文件格式,默认是parquet,指定文件格式是.format,当然也有特定格式的api,比如.json

  其中JDBC读取数据库的方式要重点说一下,在启动spark-shell时,需要注意spark的jar目录要有数据库的驱动包或者通过--jars指定,在进行读写操作时,有细节需要注意

  (1)写:创建表时默认的引擎不是Innodb;schema翻译成数据库字段的类型 不符合自己预期;设置事务隔离级别和批量写入;覆写表时的两种方式(是先删还是先清空),这些都可以通过option来设置

  (2)读:默认读是读到一个分区里,可以通过四个参数 -> 分区数,分区字段,上界,下界来划定多个分区,这四个参数可以通过option传入,也可以通过jdbc读接口传入,另外jdbc读接口支持传入一个条件列表来划定分区 ,另外 读 也可以设置批量读

  (3) 不管读还是写,都会有分区的概念,读的时候是numPartitions参数决定的,写则是df的分区数决定的,不管读还是写,分区数不宜过多,因为每个分区都会打开一个jdbc连接,连接一多容易搞垮数据库,写可以df的coalease接口来减少分区数

  (4)使用partitionBy提升性能  在写操作时通过partitionBy(分区字段名...)进行存储,数据就会按照分区字段层级建好目录进行存储,目录形式如year=2018,这样分区了的数据,使用分区目录的父目录进行读,照样可以读取出来,而schema没变,这种情况使用分区字段过滤,效率比较高(因为不用全表扫描),sql形式的过滤,分区字段会在表中显示,如果是在读取就读某个分区目录,那么分区字段不会在表中显示(因为目录路径上有体现),最后除了partitionBy可以提高性能,还可以在这分区基础上进行分bucketBy,不过此功能只能用在hive表中

 

  3.Spark SQL Column

   使用细节 :Spark SQL中DataFrame数据结构提供了DSL API让我们可以像操作表一样操作数据,那这里就设计很重要的一个概念,就是列,如果要创建列对象有三种主要的方式:1.DF.col(列名),当然可以简写成DF(列名),当然select可以直接传入字符串形式的列名,这个本质还是调用DF.col(列名)  2.使用 $"列名",这个要使用隐式转换,import spark.implicits._  3.使用col(列名)或者column(列名)或者函数表达式,这里也需要隐式转换,import org.apache.spark.sql.functions._

  untype APItype API :通俗来说,就是没有类型,说就是DataFrame数据结构,它没有明确类型,untype API就是说DF的API,type API就是说的DataSet这种强类型数据结构的API,其中他们两者col对应Column和TypedColumn,Column => TypedColumn: col(列名).as[类型]  TypedColumn => Column:typeCol.as(列名)

 

  4.Spark SQL group分组

  使用  :关注agg和pivot,agg可以同时进行多个列表操作,pivot把某一列的值转成列,有多少值就有多少列

  

  5.Spark SQL join关联

  使用 : 主要API关注join和joinWith,其中join中DF数据结构连接字段可以用字符串列,也可以用列对象的===方法,不管是两个DataSet还是DataFrame join操作返回的都是DataFrame[Row],而joinWith会返回一个每个表行值的二元组,并连接字段只能用列对象的===方法

 

问题:

  云笔记总结

  • 什么代码是在Driver端执行,什么代码在Executor端执行?

  一般初始化动作,比如sc和配置信息以及参数,还有就是生成RDD链在Driver,而Task运行,就是分区数据计算就是在Executor上

  • 一个Job有多少个Task?

  Task的数量决定了job程序运行时的并行度,而Job的Task数量主要由两个方面决定,一个就是Stage的划分,一个就是是否指定分区器(未完。。。。。)

 

答卷:

  Spark Core测试一 RDD

  Spark Core测试二 调度

  Spark Core测试试卷 spark sql

posted @ 2020-11-01 21:03  财经知识狂魔  阅读(136)  评论(0编辑  收藏  举报