SparkSQL与RDD

目录

SparkSQL

一.基础概念

二.DataFrame

三.创建DataFrame对象

四.查看DataFrame数据

五.掌 握DataFrame查询操作

RDD

一.RDD简介

二.创建RDD的三种方式

三.关于RDD的各种方法

1.map ()方法

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

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

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

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

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

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

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

9.intersection ()方法

10.使用键值对 RDD 的 keys 和 values 方法

11.使用键值对 RDD 的 groupByKey ()方法

12.使用join ()方法链接两个RDD

13.使用 zip ()方法组合两个 RDD 

14.使用 combineByKey ()方法合并相同键的值

15.使用 lookup ()方法查找指定键的值

scala

1.flatten

2、flatmap

3.filter

4.zip

5.zipWithIndex

6、foreach

7.mkString 方法


目录

SparkSQL

一.基础概念

二.DataFrame

三.创建DataFrame对象

四.查看DataFrame数据

五.掌 握DataFrame查询操作

RDD

一.RDD简介

二.创建RDD的三种方式

三.关于RDD的各种方法

1.map ()方法

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

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

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

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

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

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

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

9.intersection ()方法

10.使用键值对 RDD 的 keys 和 values 方法

11.使用键值对 RDD 的 groupByKey ()方法

12.使用join ()方法链接两个RDD

13.使用 zip ()方法组合两个 RDD 

14.使用 combineByKey ()方法合并相同键的值

15.使用 lookup ()方法查找指定键的值



SparkSQL

一.基础概念


Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象叫做DataFrame并且作为分布式SQL查询引擎的作用。
与HiveSql的区别:Hive SQL是通过转换成MapReduce任务,然后提交到集群上执行,简化了编写MapReduce的程序的复杂性。但由于MapReduce这种计算模型执行效率比较慢,Spark SQL的应运而生。SparkSQL是一个SQL解析引擎,将SQL解析成特殊的RDD(DataFrame),然后在Spark集群中运行
SparkSQL是用来处理结构化数据的(需要先将非结构化的数据转换成结构化数据)
SparkSQL的特点:
- 易整合
- 统一的数据访问格式(SparkSQL支持统一的数据源,支持读取多种类型的数据)
- 兼容Hive(元数据库、SQL语法、UDF、序列化、反序列化机制)
- 标准的数据连接(JDBC,ODBC,还可以对接常见的BI工具)

二.DataFrame


官网概念:
与RDD类似,DataFrame也是一个分布式数据容器。然而DataFrame更像传统数据库的二维表格,除了数据以外,还记录数据的结构信息,即schema。同时,与Hive类似,DataFrame也支持嵌套数据类型(struct、array和map)。从API易用性的角度上 看,DataFrame API提供的是一套高层的关系操作,比函数式的RDD API要更加友好,门槛更低。由于与R和Pandas的DataFrame类似,Spark DataFrame很好地继承了传统单机数据分析的开发体验。

理解:DataFrame是特殊的RDD,也是一种抽象RDD+schema=>DataFrame。与RDD一样,DataFrame中不存放数据,里面存放的结构化数据的描述信息(DataFrame的表头,描述了有多少列,每一列数叫什么名字、什么类型、能不能为空等)

三.创建DataFrame对象

DataFame可以通过结构化数据文件、外部数据库、Spark计算过程中生成的RDD、Hive中的表进行创建。不同数据源的数据转换成DataFrame的方式也不同。

1.通过结构化数据文件创建DataFrame

一般情况下, 结构化数据文件存储在HDFS中,较为常见的结构化数据文件是Parquet文件或JSON文件。Spark SQL可以通过load0方法将HDFS上的结构化文件数据转换为DataFrame, loadO方法默认导入的文件格式是Parquet。

2.通过外部数据库创建DataFrame

Spark SQL还可以通过外部数据库(如MySQL、Oracle 数据库)创建DataFrame,使用该方式创建DataFrame需要通过Java数据库互连( Java Database Connectivity, JDBC)连接或开放式数据库互连( Open Database Connectivity,ODBC)连接的方式访问数据库。以MySQL数据库的表数据为例,将MySQL数据库test中的people表的数据转换为DataFrame。

3.通过RDD创建DataFrame

通过RDD数据创建DataFrame有两种方式。第-种方 式是利用反射机制推断RDD模式,首先需要定义一个样例类,因为只有样例类才能被Spark隐式地转换为DataFrame。将/usr/local/spark-3.2.1-bin-hadoop2.7/examples/src/main/resources目录下的people.txt文件上传至HDFS的/user/root/sparkSql目录下。读取HDFS上的people.txt文件数据创建RDD,再将该RDD转换为DataFrame。

第二种方式是采用编程指定Schema的方式将RDD转换成DataFrame,实现步骤如下。(1 )加载数据创建RDD。

(2)使用StructType创建一个和步骤(1)的RDD中的数据结构相匹配的Schema。(3 )通过createDataFrame()方法将 Schema应用到RDD上,将RDD数据转换成DataFrame。

4.通过Hive中的表创建DataFrame

通过Hive中的表创建DataFrame,可以使用SparkSession对象。

使用SparkSession对象并调用sq10方法查询Hive中的表数据并将其转换成DataFrame,如查询test数据库中的people表数据并将其转换成DataFrame。

四.查看DataFrame数据

Spark DataFrame派生于RDD,因此类似于RDD。DataFrame 只有在提交行动操作时才进行计算

1. printSchema: 输出数据模式

创建DataFrame对象后,一-般 会查看DataFrame 的数据模式。使用printSchema函数可以查看DataFrame数据模式,输出列的名称和类型。查看DataFrame对象movies的数据模式。

2. show(): 查看数据

使用show()方法可以查看DaFame数据,可输人的参数及说明。

使用show0方法查看DataFrame对象movies中的数据,show0方法 与show(rue)方法查询到的结果一样, 只显示前20条记录,并且最多只显示20个字符。如果需要显示所有字符,那么需要使用show(false)方法。show0方法默认只显示前20条记录。若需要查看前numRows条记录则可以使用show(numRows:Int)方法,如通过“movies.show(5)”命令查看movies前5条记录。

3. first()/head()/take()takeAsList(): 获取若干条记录

获取DataFrame若干条记录除了使用show0方法之外,还可以使用frst()、head()、take()、takeAsList()方法。分别使用first()、 head()、 take()、takeAsList(方法查看movies中前几条记录)。frst0和head0方法的功能类似,以Row或Array[Row]的形式返回一条或多条数据。take0和takeAsList()方法则会将获得的数据返回Driver 端,为避免Driver提示OutofMemoryError,数据量比较大时不建议使用这两个方法。

4. collec()lcollectAsList(): 获取所有数据

collect0方法可以查询DataFrame中所有的数据,并返回一一个数组,collectAsList0方法和collect0方法类似,可以查询DataFrame中所有的数据,但是返回的是列表。分别使用collect0和collectAsList0方法查看movies所有数据。

五.掌 握DataFrame查询操作

DataFrame查询数据有两种方法,第一-种是将DataFrame注册成临时表,再通过SQL语句查询数据。第二种方法是直接在DataFrame对象上进行查询,
第二种方法是直接在DataFrame对象上进行查询。DataFrame提供了很多查询数据的方
法。类似于Spark RDD的转换操作,DataFrame 的查询操作也是懒操作,仅仅生成查询计划,只有触发行动操作才会进行计算并返回结果。

1. where()filter()方法

使用where(或filter()方法可以查询数据中符合条件的所有字段的信息。

(1 ) where(方法)

DataFrame可以使用where(conditionExpr:String)方法查询符合指定条件的数据,参数中可以使用and或or。where(方法的返回结果仍然为DataFrame。

(2) filter0方法

DataFrame还可以使用filter0方 法筛选出符合条件的数据。

2. select()/seletExpr()col()apply()方法

where0和flter0方法查询的数据包含的是所有字段的信息,但是有时用户只需要查询部分字段的值即可,DataFrame提供了查询指定字段的值的方法,如select()、selectExpr()、col()和apply()方法等,用法介绍如下.

(1 ) select()方法:获取指定字段值

select()方法根据传人的String类型字段名获取对应的值,并返回一个DataFrame对象

(2 ) selectExpr()方法:对指定字段进行特殊处理

在实际业务中,可能需要对某些字段进行特殊处理,如为某个字段取别名、对某个字段的数据进行四舍五人等。DataFrame 提供了selectExpr()方法,可以对指定字段取别名或调用UDF函数对其进行其他处理。selectExpr()方法传人String类型的参数,返回一个DataFrame对象。

(3 ) col()/apply()方法

col()和apply()方法也可以获取DataFrame指定字段,但只能获取一个字段,并且返回的是-一个 Column对象。

3. limit()方法

limitQ方法可以获取指定DataFrame数据的前n条记录。不同于take()与head()方法,limit()方法不是行动操作,因此并不会直接返回查询结果,需要结合show0方法或其他行动操作才可以显示结果。

4. orderBy()/sort()方法 

orderBy()方法用于根据指定字段对数据进行排序,默认为升序排序。若要求降序排序,orderBy()方法的参数可以使用“desc("字段名称")” 或“$"字段名称" .desc",也可以在指定字段前面加“-”。

5. groupBy()方法

使用groupBy()方法可以根据指定字段对数据进行分组操作。groupBy()方法的输人参数既可以是String类型的字段名,也可以是Column对象。

6. join()方法

数据并不- -定都存放在同一个表中,也有可能存放在两个或两个以上的表中。根据业务需求,有时候需要连接两个表才可以查询出业务所需的数据。DataFrame 提供了join()方法用于连接两个表。

RDD

一.RDD简介

1.RDD是Spark的核心抽象,全称为Resillient Distributed Dataset,即弹性分布式数据集
2.RDD在抽象上来说是一种元素集合,包含了数据。它是被分区的,分为多个分区,每个分区分布3.在集群中的不同节点上(分区即partition),从而让RDD中的数据可以被并行操作。(分布式的特性)
4.RDD通常通过Hadoop上的文件,即HDFS文件,来进行创建;有时也可以通过Spark应用程序中的集合来创建。
5.RDD最重要的特性就是,提供了容错性,可以自动从节点失败中恢复过来。即如果某个节点上的6.RDD partition,因为节点故障,导致数据丢了,那么RDD会自动通过自己的数据来源重新计算7.partition。这一切对使用者是透明的。
8.RDD的数据默认的情况下是存放在内存中的,但是在内存资源不足时,Spark会自动将RDD数据写

二.创建RDD的三种方式

在RDD中,通常就代表和包含了Spark应用程序的输入源数据。
当我们,在创建了初始的RDD之后,才可以通过Spark Core提供的transformation算子,对该RDD进行transformation(转换)操作,来获取其他的RDD。
Spark Core为我们提供了三种创建RDD的方式,包括:
1. 使用程序中的集合创建RDD
2. 使用本地文件创建RDD
3. 使用HDFS文件创建RDD

三.关于RDD的各种方法
1.map ()方法

方法是一种基础的 RDD 转换操作,可以对 RDD 中的每一个数据元素通过某种函数进行转换并返回新的 RDD 。 map ()方法是懒操作,不会立即进行计算。
转换操作是创建 RDD 的第二种方法,通过转换已有 RDD 生成新的 RDD 。因为 RDD 是一个不可变的集合,所以如果对 RDD 数据进行了某种转换,那么会生成一个新的 RDD。

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


 sortBy ()方法用于对标准 RDD 进行排序,有3个可输入参数,说明如下。
(1)第1个参数是一个函数 f :( T )=> K ,左边是要被排序对象中的每一个元素,右边返回的值是元素中要进行排序的值。
(2)第2个参数是 ascending ,决定排序后 RDD 中的元素是升序的还是降序的,默认是 true ,即升序排序,如果需要降序排序则需要将参数的值设置为 false 。
(3)第3个参数是 numPartitions ,决定排序后的 RDD 的分区个数,默认排序后的分区个数和排序之前的分区个数相等,即 this . partitions . size 。
第一个参数是必须输入的,而后面的两个参数可以不输入。

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


 collect ()方法是一种行动操作,可以将 RDD 中所有元素转换成数组并返回到 Driver 端,适用于返回处理后的少量数据。因为需要从集群各个节点收集数据到本地,经过网络传输,并且加载到 Driver 内存中,所以如果数据量比较大,会给网络传输造成很大的压力。因此,数据量较大时,尽量不使用 collect ()方法,否则可能导致 Driver 端出现内存溢出问题。 collect ()方法有以下两种操作方式。
(1) collect :直接调用 collect 返回该 RDD 中的所有元素,返回类型是一个 Array [ T ]数组,这是较为常用的一种方式。
使用 collect ()方法查看 sq _ dist 和 sort _ data 的结果, 分别返回了经过平方运算后的 Int 类型的数组和对元组第二个值进行降序排列后的数组。(2) collect [ U : ClassTag ]( f : PartialFunction [ T , U ]): RDD [ U ]。这种方式需要提供一个标准的偏函数,将元素保存至一个 RDD 中。首先定义一个函数 one ,用于将 collect 方法得到的数组中数值为1的值替换为" one ",将其他值替换为" other "。创建一个只有3个 Int 类型数据的 RDD ,在使用 collect ()方法时将 one 函数作为参数。

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


 flatMap ()方法将函数参数应用于 RDD 之中的每一个元素,将返回的迭代器(如数组、列表等)中的所有元素构成新的 RDD 。使用 flatMap ()方法时先进行 map (映射)再进行 flat (扁平化)操作,数据会先经过跟 map ()方法一样的操作,为每一条输入返回一个迭代器(可迭代的数据类型),然后将所得到的不同级别的迭代器中的元素全部当成同级别的元素,返回一个元素级别全部相同的 RDD 。这个转换操作通常用来切分单词。
例如,分别用 map ()方法和 flatMap ()方法分割字符串。用 map ()方法分割后,每个元素对应返回一个迭代器,即数组。 

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


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

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


union方法是一种转换操作,用于将两个 RDD 合并成一个,不进行去重操作,而且两个 RDD 中每个元素中的值的个数、数据类型需要保持一致。创建两个存放二元组的 RDD ,通过 union ()方法合并两个 RDD ,不处理重复数据,并且每个二元组的值的个数、数据类型都是一致的。

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


 filter ()方法是一种转换操作,用于过滤 RDD 中的元素。 filter ()方法需要一个参数,这个参数是一个用于过滤的函数,该函数的返回值为 Boolean 类型。 filter ()方法将返回值为 true 的元素保留,将返回值为 false 的元素过滤掉,最后返回一个存储符合过滤条件的所有元素的新 RDD 。

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


 distinct ()方法是一种转换操作,用于 RDD 的数据去重,去除两个完全相同的元素,没有参数。

9.intersection ()方法


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

(2) subtract ()方法
 subtract ()方法用于将前一个 RDD 中在后一个 RDD 出现的元素删除,可以认为是求补集的操作,返回值为前一个 RDD 去除与后一个 RDD 相同元素后的剩余值所组成的新的 RDD 。两个 RDD 的顺序会影响结果。

(3) cartesian ()方法
 cartesian ()方法可将两个集合的元素两两组合成一组,即求笛卡儿积。假设集合 A 有5个元素,集合 B 有10个元素,集合 A 的每个元素都会和集合 B 的每个元素组合成一组,结果会返回50个元素组合。

10.使用键值对 RDD 的 keys 和 values 方法


键值对 RDD ,包含键和值两个部分。 Spark 提供了两种方法,分别获取键值对 RDD 的键和值。 keys 方法返回一个仅包含键的 RDD , values 方法返回一个仅包含值的 RDD 。

使用键值对 RDD 的 reduceByKey ()方法
当数据集以键值对形式展现时,合并统计键相同的值是很常用的操作。 reduceByKey ()方法用于合并具有相同键的值,作用对象是键值对,并且只对键的值进行处理。 reduceByKey (方法需要接收一个输入函数,键值对 RDD 相同键的值会根据函数进行合并,并创建一个新的 RDD 作为返回结果。
在进行处理时, reduceByKey ()方法将相同键的前两个值传给输入函数,产生一个新的返回值,新产生的返回值与 RDD 中相同键的下一个值组成两
个元素,再传给输入函数,直到最后每个键只有一个对应的值为止。 reduceByKey )方法不是一种行动操作,而是一种转换操作
定义一个含有多个相同键的键值对 RDD ,使用 reduceByKey ()方法对每个键的值进行求和。

11.使用键值对 RDD 的 groupByKey ()方法


 groupByKey ()方法用于对具有相同键的值进行分组,可以对同一组的数据进行计数、求和等操作。对于一个由类型 K 的键和类型 V 的值组成的 RDD ,通过 groupByKey ()方法得到的 RDD 类型是[ K , Iterable [ V ]]。

12.使用join ()方法链接两个RDD


join ()方法用于根据键对两个 RDD 进行内连接,将两个 RDD 中键相同的数据的值存放在一个元组中,最后只返回两个 RDD 中都存在的键的连接结果。例如,在两个 RDD 中分别有键值对( K , V )和( K , W ),通过 join ()方法连接会返回( K ,( V , W ))。

13.使用 zip ()方法组合两个 RDD 


 zip (方法用于将两个 RDD 组合成键值对 RDD ,要求两个 RDD 的分区数量以及元素数
量相同,否则会抛出异常。
将两个非键值对 RDD 组合成一个键值对 RDD ,两个 RDD 的元素个数和分区个数都相同。

14.使用 combineByKey ()方法合并相同键的值


combineByKey0方法是 Spark 中一个比较核心的高级方法,键值对的一些其他高级方法的底层均是使用 combineByKey ()方法实现的,如 groupBy - Key ()方法、 reduceByKey ()方法等。
 combineByKey ()方法用于将键相同的数据合并,并且允许返回与输入数据的类型不同的返回值。

15.使用 lookup ()方法查找指定键的值


 lookup ( key : K )方法用于返回键值对 RDD 指定键的所有对应值。例如,通过 lookup ()方法查询 test 中键为 panda 的所有对应值。

scala

1.flatten


可以把嵌套的结构展开. 

scala> List(List(1,2),List(3,4)).flatten
res0: List[Int] = List(1, 2, 3, 4)

2、flatmap


flatMap结合了map和flatten的功能。接收一个可以处理嵌套列表的函数,然后把返回结果连接起来。

scala> List(List(1,2),List(3,4)).flatMap(x=>x.map(x=>x*2))
res5: List[Int] = List(2, 4, 6, 8)

3.filter


滤除掉使函数返回false的元素

scala> def isEven(i: Int): Boolean = i % 2 == 0
isEven: (i: Int)Boolean
scala> List(1,2,3,4).filter(isEven _)
res6: List[Int] = List(2, 4)

4.zip


zip方法将两个集合结合在一起

scala>  List('a,'b,'c).zip(List(1,2,3))
res32: List[(Symbol, Int)] = List(('a,1), ('b,2), ('c,3))

5.zipWithIndex


将元素和下标结合在一起

scala> List(2,3,4,5).zipWithIndex
res33: List[(Int, Int)] = List((2,0), (3,1), (4,2), (5,3))

6、foreach


foreach和map相似,只不过它没有返回值,foreach只要是为了对参数进行作用。

比如 names.foreach{name=>println(name)}

7.mkString 方法


scala通过mkString方法把一个集合转化为一个字符串

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值