目录
一、概述
概述
1、SparkSQL是Spark发展后期产生的,是为了使用SQL风格来替换之前SparkCore的RDD风格
2、SparkSQL既可以做离线,也可以做实时
3、SparkSQL的编程有两种风格:SQL风格、DSL分格
SparkCore的缺点
- 场景:在大数据业务场景中,经常处理结构化的数据,数据来源往往是一些结构化数据,结构化的文件,对于结构化的数据处理最方便的开发接口就是SQL接口
- 问题:SparkCore类似于MapReduce的编程方式,写代码,提交运行,构建对象实例RDD,调用函数来处理,SparkCore处理结构化的数据非常不方便,不能很好的基于列进行处理,每次都需要分割.
二、SparkSQL和SparkCore区别
SparkSQL和SparkCore区别
1、SparkCore的核心数据类型是RDD,SparkSQL核心数据类型是DataFrame
2、SparkCore的入门核心类是SparkContext、SparkSQL的核心入口类是:SparkSession
3、SparkSQL是基于SparkCore,SparkSQL代码底层就是rdd
4、SparkCore只侧重数据本身,没有表概念,SparkSQL要侧重:数据+表结构
三、dataFrame
概述
RDD + Schema信息(表结构) = dataFrame
dataFrame的表结构
1、DataFrame本质上一张二维表格,每一个DataFrame都有表结构信息,表结构被称为Schema信息
2、DataFrame每一列的表结构用StructField类来描述、DataFrame每一行的表结构用Row类来描述,DataFrame整个的表结构用StructType类来描述
#如何打印DataFrame的表结构信息
#方式1
print(dataFrame2.schema)
"""
StructType(List(StructField(word,StringType,true),StructField(cnt,LongType,false)))
"""
#方式2
dataFrame2.printSchema()
"""
root
|-- word: string (nullable = true)
|-- cnt: long (nullable = false)
#long是比int更大的整数类型,存储的最大数: 9223372036854775808
"""
RDD转为dataFrame
为什么要将RDD转为DataFrame?
1、如果你遇到一个非结构化数据,则我们可以先将数据转为RDD,利用RDD算子对数据进行转换,转换为结构化数据,再转为DataFrame,然后用于数据分析。
#非结构化数据--->RDD--->用算子转换--->结构化数据--->DataFrame
2、如果你遇到一个结构化数据,但是需要对数据进行清洗,则可以先转为RDD,清洗完之后再转为DataFrame #结构化数据--->RDD--->用算子清洗--->清洗后结构化数据--->DataFrame
怎么将RDD转为DataFrame?
方式1-自动推断类型转换
#4、将rdd1的数据进行清洗,清洗之后转为4元组rdd,并去掉时间两边的[]
"""
'196 242 3 [881250949]' ---->RDD[ROW(196,242,3,881250949)]
"""
rdd2 = rdd1.map(lambda x:Row(userid=x.split()[0],movieid=x.split()[1],rate=int(x.split()[2]),ts=int(x.split()[3][1:-1])))
print(rdd2.collect())
#5、将rdd2转为DataFrame
dataFrame1 = spark.createDataFrame(rdd2)
dataFrame1.show()
方式2-自定义Schema转换
#4、将rdd1的数据进行清洗,清洗之后转为4元组rdd,并去掉时间两边的[]
"""
'196 242 3 [881250949]' ---->RDD[(196,242,3,881250949)]
"""
rdd2 = rdd1.map(lambda x:(x.split()[0],x.split()[1],int(x.split()[2]),int(x.split()[3][1:-1])))
print(rdd2.collect())
#4、定义schema信息
#这里创建StructType对象,参数是一个对象列表,列表中存的是StructField对象
movie_schema = StructType([
StructField(name='userid',dataType=StringType(),nullable=True),
StructField(name='movieid',dataType=StringType(),nullable=True),
StructField(name='rate',dataType=IntegerType(),nullable=True),
StructField(name='ts',dataType=LongType(),nullable=True)
])
#5、将RDD和schema合并,转为DataFrame
dataFrame1 = spark.createDataFrame(rdd2,movie_schema)
dataFrame1.show()
方式3-指定列名称转换(掌握)
#4、将rdd1的数据进行清洗,清洗之后转为4元组rdd,并去掉时间两边的[]
"""
'196 242 3 [881250949]' ---->RDD[(196,242,3,881250949)]
"""
rdd2 = rdd1.map(lambda x:(x.split()[0],x.split()[1],int(x.split()[2]),int(x.split()[3][1:-1])))
print(rdd2.collect())
#5、直接转为DataFrame,这里只需要指定每一列的名字即可
dataFrame1 = rdd2.toDF(['userid','movieid','rate','ts'])
dataFrame1.show()
dataFrame1.printSchema()
dataFrame调用类RDD函数
概述
1、DataFrame几乎可以调用RDD绝大多数的算子
2、如果DataFrame不能调用RDD的某个算子,则可以先将DataFrame转为RDD再调用算子
代码
# 3、演示DataFrame可以调用的类RDD算子函数
# - count:统计行数
print(df1.count()) # select count(*) from t_movie;
# - collect:将DataFrame转换成一个列表
list1 = df1.collect();
for x in list1:
# print(x.user_id,x.movie_id,x.rate,x.ts)
print(x['user_id'],x['movie_id&#