Spark SQL结构化数据文件处理知识总结

目录

一、 Spark SQL的简介

1.1 Spark SQL的简介 

 1.2 Spark SQL架构

二、DataFrame概述 

2.1DataFrame简介

2.2 Spark SQL数据抽象 

2.2.1 DataFrame 和 DataSet

2.3 DataFrame的创建

三、Scala基础

一.Scala常用数据类型 

二.定义与使用数组

三.定义与使用函数

四.定义与使用列表

五.定义与使用集合

六.定义与使用映射

七.定义与使用元组

四、Spark编程基础

一.从内存中读取创建RDD

二.从外部存储系统中读取数据创建RDD

五、RDD方法归纳

1.使用map()方法转换数据 map()方法是一种基础的RDD转换操作,可以对 RDD 中的每一个数据元素通过某种函数进行转换并返回新的RDD。mapO方法是懒操作,不会立即进行计算。

2.使用 sortBy()方法进行排序

3.使用collect()方法查询数据

4.使用flatMap()方法转换数据

5.使用take()方法查询某几个值

6.使用union()方法合并多个RDD

7.使用filter()方法进行过滤

8.使用distinct()方法进行去重

六、使用简单的集合操作

(1)intersection()方法

(2)subtract()方法

(3)cartesian()方法

七、Spark SQL 多数据源交互

1.读取文件

2.写入文件

七、数据抽象 

7.1DStream 本质上就是一系列时间上连续的 RDD: 

7.2 对 DStream 的数据的进行操作也是按照 RDD 为单位来进行的:

7.3 容错性

7.4 准实时性/近实时性


一、 Spark SQL的简介

1.1 Spark SQL的简介 

Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象结构叫做DataFrame的数据模型(即带有Schema信息的RDD),Spark SQL作为分布式SQL查询引擎,让用户可以通过SQL、DataFrames API和Datasets API三种方式实现对结构化数据的处理。

Spark SQL主要提供了以下三个功能:

  1. Spark SQL可从各种结构化数据源中读取数据,进行数据分析。
  2. Spark SQL包含行业标准的JDBC和ODBC连接方式,因此它不局限于在Spark程序内使用SQL语句进行查询。
  3. Spark SQL可以无缝地将SQL查询与Spark程序进行结合,它能够将结构化数据作为Spark中的分布式数据集(RDD)进行查询。

Hive 是将 SQL 转为 MapReduce。 

SparkSQL 可以理解成是将 SQL 解析成:“RDD + 优化” 再执行 

在学习Spark SQL前,需要了解数据分类

总结:

  • RDD 主要用于处理非结构化数据 、半结构化数据、结构化;
  • SparkSQL 是一个既支持 SQL 又支持命令式数据处理的工具;
  • SparkSQL 主要用于处理结构化数据(较为规范的半结构化数据也可以处理)

 1.2 Spark SQL架构

Spark SQL架构与Hive架构相比,把底层的MapReduce执行引擎更改为Spark,还修改了Catalyst优化器,Spark SQL快速的计算效率得益于Catalyst优化器。从HiveQL被解析成语法抽象树起,执行计划生成和优化的工作全部交给Spark SQL的Catalyst优化器进行负责和管理。

Spark要想很好地支持SQL,需要完成解析(Parser)、优化(Optimizer)、执行(Execution)三大过程。 

Catalyst优化器在执行计划生成和优化的工作时,离不开内部的五大组件。

  1. SqlParse:完成SQL语法解析功能,目前只提供了一个简单的SQL解析器。
  2. Analyze:主要完成绑定工作,将不同来源的Unresolved LogicalPlan和元数据进行绑定,生成Resolved LogicalPlan。
  3. Optimizer:对Resolved Lo;gicalPlan进行优化,生成OptimizedLogicalPlan。
  4. Planner:将LogicalPlan转换成PhysicalPlan。
  5. CostModel:主要根据过去的性能统计数据,选择最佳的物理执行计划

二、DataFrame概述 

2.1DataFrame简介

  • Spark SQL使用的数据抽象并非是RDD,而是DataFrame。
  • 在Spark 1.3.0版本之前,DataFrame被称为SchemaRDD。
  • DataFrame使Spark具备处理大规模结构化数据的能力。
  • 在Spark中,DataFrame是一种以RDD为基础的分布式数据集。
  • DataFrame的结构类似传统数据库的二维表格,可以从很多数据源中创建,如结构化文件、外部数据库、Hive表等数据源。

DataFrame可以看作是分布式的Row对象的集合,在二维表数据集的每一列都带有名称和类型,这就是Schema元信息,这使得Spark框架可获取更多数据结构信息,从而对在DataFrame背后的数据源以及作用于DataFrame之上数据变换进行针对性的优化,最终达到提升计算效率。

2.2 Spark SQL数据抽象 

2.2.1 DataFrame 和 DataSet

Spark SQL数据抽象可以分为两类:

  1. DataFrame:DataFrame 是一种以 RDD 为基础的分布式数据集,类似于传统数据库的二维表格,带有 Schema 元信息(可以理解为数据库的列名和类型)。DataFrame = RDD + 泛型 + SQL 的操作 + 优化
  2. DataSet:DataSet是DataFrame的进一步发展,它比RDD保存了更多的描述信息,概念上等同于关系型数据库中的二维表,它保存了类型信息,是强类型的,提供了编译时类型检查。调用 Dataset 的方法先会生成逻辑计划,然后被 spark 的优化器进行优化,最终生成物理计划,然后提交到集群中运行!DataFrame = Dateset[Row]

2.3 DataFrame的创建

创建DataFrame的两种基本方式:

  1. 已存在的RDD调用toDF()方法转换得到DataFrame。
  2. 通过Spark读取数据源直接创建DataFrame。

若使用SparkSession方式创建DataFrame,可以使用spark.read从不同类型的文件中加载数据创建DataFrame。spark.read的具体操作,在创建Dataframe之前,为了支持RDD转换成Dataframe及后续的SQL操作,需要导入import.spark.implicits._包启用隐式转换。若使用SparkSession方式创建Dataframe,可以使用spark.read操作,从不同类型的文件中加载数据创建DataFrame。

三、Scala基础

一.Scala常用数据类型 

Scala的数据类型与Java数据类型相似,但不同于Java,Scala没有原生的数据类型。Scala的数据类型均为对象,因此通过数据类型可以调用方法。

​ 在Scala中,所有数据类型的第一个字母都必须大写

scala中常用的数据类型: 

  • Scala会区分不同类型的值,并且会基于使用值的方式确定最终结果的数据类型,这称为类型推断

  • Scala使用类型推断可以确定混合使用数据类型时最终结果的数据类型。

    如在加法中混用Int和Double类型时,Scala将确定最终结果为Double类型,如下图。

二.定义与使用数组

数组是Scala中常用的一种数据结构,数组是一种存储了相同类型元素的固定大小的顺序集合,Scala定义一个数组的语法格式如下:

# 第1种方式

var arr: Array[String] = new Array[String](num)

# 第2种方式

var arr:Array[String] = Array(元素1,元素2,…)

三.定义与使用函数

函数是Scala的重要组成部分,Scala作为支持函数式编程的语言,可以将函数作为对象.定义函数的语法格式如下:

# def functionName(参数列表):[return type]={}

Scala提供了多种不同的函数调用方式,以下是调用函数的标准格式。

# functionName(参数列表)

如果函数定义在一个类中,那么可以通过“类名.方法名(参数列表)”的方式调用

四.定义与使用列表

列表操作常用方法

Scala中常用的查看列表元素的方法有head、init、last、tail和take()。

1.head:查看列表的第一个元素。

2.tail:查看第一个元素之后的其余元素。

3.last:查看列表的最后一个元素。

4.Init:查看除最后一个元素外的所有元素。

5.take():查看列表前n个元素。

五.定义与使用集合

Scala Set(集合)是没有重复的对象集合,所有的元素都是唯一的

集合操作常用方法

 Scala合并两个列表时使用的是:::()或concat()方法,而合并两个集合使用的是++()方法。

六.定义与使用映射

1. 映射( Map ) 是一种可迭代的键值对结构 。

2. 所有的值都可以通过键来获取 ,并且映射中的键都是唯一的 。

3. 集合操作常用方法同样也适合映射。

4. 另外映射还可以通过 keys 方法获取所有的键,通过 values 方法获取所有值,也可以通过 isEmpty 方法判断映射的数据是否为空

七.定义与使用元组

1.元组(Tuple)是一种类似于列表的结构,但与列表不同的是,元组可以包含不同类型的元素。

2.元组的值是通过将单个的值包含在圆括号中构成的

3.目前,Scala支持的元组最大长度为22,即Scala元组最多只能包含22个元素

4.访问元组元素可以通过“元组名称._元素索引”进行,索引从1开始

四、Spark编程基础

一.从内存中读取创建RDD

1.parallelize()

parallelizeO方法有两个输人参数,说明如下:

(1)要转化的集合:必须是 Seq集合。Seq 表示序列,指的是一类具有一定长度的、可迭代访问的对象,其中每个数据元素均带有一个从0开始的、固定的索引。

(2)分区数。若不设分区数,则RDD 的分区数默认为该程序分配到的资源的 CPU核心数。

2.makeRDD()

makeRDD0方法有两种使用方式,第一种使用方式与 parallelize0方法一致;第二种方式是通过接收一个 Seq[(T,Seq[String])]参数类型创建 RDD。第二种方式生成的RDD中保存的是T的值,Seq[String]部分的数据会按照 Seqf(T,Seq[String])的顺序存放到各个分区中,一个 Seq[Stringl对应存放至一个分区,并为数据提供位置信息,通过preferredLocations0方法可以根据位置信息查看每一个分区的值。调用 makeRDD0时不可以直接指定 RDD 的分区个数,分区的个数与 Seq[String]参数的个数是保持一致的。

使用 makeRDD0方法创建 RDD,并根据位置信息查看每一个分区的值,结果如图所示。

二.从外部存储系统中读取数据创建RDD

1.从外部存储系统中读取数据创建RDD是指直接读取存放在文件系统中的数据文件创建RDD。从内存中读取数据创建 RDD 的方法常用于测试,从外部存储系统中读取数据创建 RDD 才是用于实践操作的常用方法。

2.从外部存储系统中读取数据创建 RDD 的方法可以有很多种数据来源,可通过SparkContext对象的 textFile0方法读取数据集。textFileO方法支持多种类型的数据集,如目录、文本文件、压缩文件和通配符匹配的文件等,并且允许设定分区个数,分别读取 HDFS文件和Linux本地文件的数据并创建 RDD,具体操作如下。

(1)通过HDFS文件创建 RDD

这种方式较为简单和常用,直接通过 textFile()方法读取 HDFS文件的位置即可。

在HDFS 的/user/toot 目录下有一个文件test.txt,读取该文件创建一个 RDD,代码如下

val test = sc. textile ("/user/root/test.txt")

(2)通过 Linux 本地文件创建 RDD

本地文件的读取也是通过 sc.textFile("路径")的方法实现的,在路径前面加上“file://”表示从Linux 本地文件系统读取。在 IntelliJIDEA 开发环境中可以直接读取本地文件;但在 spark-shell 中,要求在所有节点的相同位置保存该文件才可以读取它,例如,在Linux的/opt 目录下创建一个文件 test.txt,任意输入4行数据并保存,将 test.txt 文件远程传输至所有节点的/opt 目录下,才可以读取文件 test.txt。读取 test.txt 文件,并且统计文件的数据行数,代码如下

五、RDD方法归纳

1.使用map()方法转换数据
 map()方法是一种基础的RDD转换操作,可以对 RDD 中的每一个数据元素通过某种函数进行转换并返回新的RDD。mapO方法是懒操作,不会立即进行计算。

 转换操作是创建RDD的第二种方法,通过转换已有RDD生成新的RDD。因为RDD是一个不可变的集合,所以如果对 RDD 数据进行了某种转换,那么会生成一个新的 RDD。

2.使用 sortBy()方法进行排序

sortBy0方法用于对标准RDD 进行排序,有3个可输人参数,说明如下。

(1)第1个参数是一个函数f:(T)=>K,左边是要被排序对象中的每一个元素,右边返回的值是元素中要进行排序的值。

(2)第2个参数是 ascending,决定排序后 RDD 中的元素是升序的还是降序的,默认是 true,即升序排序,如果需要降序排序则需要将参数的值设置为 false。

(3)第3个参数是numPartitions,决定排序后的RDD 的分区个数,默认排序后的分区个数和排序之前的分区个数相等,即 this.partitions.size。

第一个参数是必须输人的,而后面的两个参数可以不输人。例如,通过一个存放了 3个二元组的列表创建一个 RDD,对元组的第二个值进行降序排序,分区个数设置为1,代码如下

3.使用collect()方法查询数据

collectO方法是一种行动操作,可以将 RDD 中所有元素转换成数组并返回到 Driver 端,适用于返回处理后的少量数据。因为需要从集群各个节点收集数据到本地,经过网络传输,并且加载到 Driver 内存中,所以如果数据量比较大,会给网络传输造成很大的压力。因此,数据量较大时,尽量不使用collectO方法,否则可能导致Driver 端出现内存溢出间题。collectO方法有以下两种操作方式。

(1) collect:直接调用 collect 返回该 RDD 中的所有元素,返回类型是一个 Array[T数组,这是较为常用的一种方式。

(2)collect[U: ClassTag](f: PartialFunction[T, U]):RDD[U]。这种方式需要提供一个标准的偏函数,将元素保存至一个RDD中。首先定义一个函数one,用于将collect方法得到的数组中数值为1的值替换为“one”,将其他值替换为“other”。

4.使用flatMap()方法转换数据

flatMap()方法将函数参数应用于RDD之中的每一个元素,将返回的迭代器(如数组、列表等)中的所有元素构成新的RDD。

        使用flatMap()方法时先进行map(映射)再进行flat(扁平化)操作,数据会先经过跟map一样的操作,为每一条输入返回一个迭代器(可迭代的数据类型),然后将所得到的不同级别的迭代器中的元素全部当成同级别的元素,返回一个元素级别全部相同的RDD。这个转换操作通常用来切分单词。

        例如,分别用 maPO方法和 AatapO方法分制字符串。用 mapO方法分削后,每个元素对应返回一个迷代器,即数组。fatNapO方法在进行同 mapO方法一样的操作后,将3个选代器的元素扁平化(压成同一级别),保存在新 RDD 中,代码如下

5.使用take()方法查询某几个值

 take(N)方法用于获取RDD的前N个元素,返回数据为数组。take()与collect()方法的原理相似,collect()方法用于获取全部数据,take()方法获取指定个数的数据。获取RDD的前5个元素,代码如下。

6.使用union()方法合并多个RDD

  union()方法是一种转换操作,用于将两个RDD合并成一个,不进行去重操作,而且两个RDD中每个元素中的值的个数、数据类型需要保持一致。代码如下

7.使用filter()方法进行过滤

filter()方法是一种转换操作,用于过滤RDD中的元素。

filter()方法需要一个参数,这个参数是一个用于过滤的函数,该函数的返回值为Boolean类型。

filter()方法将返回值为true的元素保留,将返回值为false的元素过滤掉,最后返回一个存储符合过滤条件的所有元素的新RDD。

创建一个RDD,并且过滤掉每个元组第二个值小于等于1的元素。代码如下

8.使用distinct()方法进行去重

 distinct()方法是一种转换操作,用于RDD的数据去重,去除两个完全相同的元素,没有参数。创建一个带有重复数据的RDD,并使用distinct()方法去重。代码如下

六、使用简单的集合操作

(1)intersection()方法

intersection()方法用于求出两个RDD的共同元素,即找出两个RDD的交集,参数是另一个RDD,先后顺序与结果无关。创建两个RDD,其中有相同的元素,通过intersection()方法求出两个RDD的交集

(2)subtract()方法

subtract()方法用于将前一个RDD中在后一个RDD出现的元素删除,可以认为是求补集的操作,返回值为前一个RDD去除与后一个RDD相同元素后的剩余值所组成的新的RDD。两个RDD的顺序会影响结果。创建两个RDD,分别为rdd1和rdd2,包含相同元素和不同元素,通过subtract()方法求rdd1和rdd2彼此的补集。

(3)cartesian()方法

cartesian()方法可将两个集合的元素两两组合成一组,即求笛卡儿积。创建两个RDD,分别有4个元素,通过cartesian()方法求两个RDD的笛卡儿积。

over

七、Spark SQL 多数据源交互

1.读取文件

读取 json 文件:

spark.read.json("D:\\data\\output\\json").show()

读取 csv 文件:

spark.read.csv("D:\\data\\output\\csv").toDF("id","name","age").show()

读取 parquet 文件: 

spark.read.parquet("D:\\data\\output\\parquet").show()

读取 mysql 表: 

val prop = new Properties()
    prop.setProperty("user","root")
    prop.setProperty("password","root")
spark.read.jdbc(
"jdbc:mysql://localhost:3306/bigdata?characterEncoding=UTF-8","person",prop).show()

2.写入文件

写入 json 文件:

personDF.write.json("D:\\data\\output\\json")

写入 csv 文件:

personDF.write.csv("D:\\data\\output\\csv")

写入 parquet 文件:

personDF.write.parquet("D:\\data\\output\\parquet")

写入 mysql 表:

val prop = new Properties()
    prop.setProperty("user","root")
    prop.setProperty("password","root")
personDF.write.mode(SaveMode.Overwrite).jdbc(
"jdbc:mysql://localhost:3306/bigdata?characterEncoding=UTF-8","person",prop)

七、数据抽象 

Spark Streaming 的基础抽象是 DStream(Discretized Stream,离散化数据流,连续不断的数据流),代表持续性的数据流和经过各种 Spark 算子操作后的结果数据流。

可以从以下多个角度深入理解 DStream:

7.1DStream 本质上就是一系列时间上连续的 RDD: 

7.2 对 DStream 的数据的进行操作也是按照 RDD 为单位来进行的:

7.3 容错性

底层 RDD 之间存在依赖关系,DStream 直接也有依赖关系,RDD 具有容错性,那么 DStream 也具有容错性。

7.4 准实时性/近实时性

Spark Streaming 将流式计算分解成多个 Spark Job,对于每一时间段数据的处理都会经过 Spark DAG 图分解以及 Spark 的任务集的调度过程。
对于目前版本的 Spark Streaming 而言,其最小的 Batch Size 的选取在 0.5~5 秒钟之间。
所以 Spark Streaming 能够满足流式准实时计算场景,对实时性要求非常高的如高频实时交易场景则不太适合。

  • 36
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值