笔记二十:Spark基础_06

SparkSQL?

SparkSQL是Spark中专门为结构化数据计算的模块,基于SparkCore之上

特点
- Integrated:集成了大多数的开发接口【Python、Scala、Java、SQL】
- Uniform Data Access:统一化的数据访问【集成了大量读写数据源接口】
- Hive Integration:Hive的集成【兼容90%以上Hive的语法:DDL、DML、DQL】
- Standard Connectivity:标准的数据连接接口【JDBC、SQL文件、Python文件】
SparkCore和SparkSQL对比

 

 

DataFrame的设计

本质
DataFrame = RDD + Schema

# Schema是元数据的抽象集合,包括表、列、数据类型、视图、存储过程等

区别
# JSON数据源文件

{"name":"Michael", "salary":3000}
{"name":"Andy", "salary":4500}
{"name":"Justin", "salary":3500}
{"name":"Berta", "salary":4000}
RDD读取
input_rdd = spark.sparkContext.textFile("../data/json")
input_rdd.foreach(lambda x: print(x))

# 会将每条数据作为一个字符串,进行输出,并不会解析数据中有列

 

DataFrame读取
input_df = spark.read.json("../data/json")
input_df.printSchema()
input_df.show()

 从DataFrame中获取RDD和Schema
# 关系 DataFrame = RDD + Schema

# 从Df中获取RDD
input_df_rdd = input_df.rdd
input_df_rdd.foreach(lambda x: print(x))

# 从DF中获取Schema
input_df_schema = input_df.schema
print(*input_df_schema)

DataFrame的创建

# 创建DataFrame即创建SparkSession

spark = SparkSession.builder.master("local[2]").appName("SparkSession").getOrCreate()
自动推断类型转换
# 当数据源是半结构化数据或者特殊格式的数据,不能直接使用SparkSQL进行处理
# 先用SparkCore将非结构化数据进行清洗转化成结构化数据,然后使用SparkSQL进行统计分析

 

# 自动推断类型转换
# 将RDD中每条数据转换成Row类型,Spark可以自动将RDD转换成DataFrame

# 数据源

userid【用户ID】 movieid【电影ID】 rate【评价】 ts【时间戳】
196	            242	              3	          881250949
186	            302	              3	          891717742
22	            377               1           878887116
244	            51	              2	          880606923
196	            242               3           881250949
186	            302	              3	          891717742
22	            377	              1	          878887116
244	            51	              2	          880606923
# 实现转换

# step1: 读取数据
# 用RDD方式进行读取
movie_rdd = spark.sparkContext.textFile("../data")

# step2: 处理数据
"""自动推断:RDD中每条数据必须为Row类型,Spark就可以实现自动推断"""
# a.将str类型的RDD变成Row类型的RDD
movie_rdd_row = ( movie_rdd
                  # 先将每个字符串分割,变成列表
                  .map(lambda line: re.split("\\s+", line))
                  # 将每个列表转换成一条Row类型对象数据
              .map(lambda item: Row(userid=item[0], movieid=item[1],
rate=float(item[2]), ts=int(item[3])))
)

# b.将RDD转换成DF
movie_df = spark.createDataFrame(movie_rdd_row)

# step3: 保存结果
movie_df.printSchema()
movie_df.show()

 

自定义Schema转换
# step1: 读取数据
# a.读取数据放入RDD中
move_rdd_str = spark.sparkContext.textFile("../data")

# step2: 处理数据
# b.转换为DataFrame
"""自定义Schema:构建一个元素或者列表类型的RDD,
自定义一个Schema对象StructType,将RDD和Schema对象合并"""
# 先构建元组类型的RDD
movie_rdd_tuple = (move_rdd_str
                   # 将一行一个字符串转换成一个列表
                   .map(lambda line: re.split("\\s+", line))
                   # 将一行一个列表转换成一个元组对象
                   .map(lambda item: (item[0], item[1], float(item[2]), int(item[3])))
                   )

# 自定义一个Schema对象
movie_schema = StructType([
    StructField(name="userid", dataType=StringType(), nullable=True),
    StructField(name="movieid", dataType=StringType(), nullable=True),
    StructField(name="rate", dataType=DoubleType(), nullable=True),
    StructField(name="ts", dataType=LongType(), nullable=True)
])

# 将RDD和Schema合并,转换为DataFrame
movie_df = spark.createDataFrame(movie_rdd_tuple, movie_schema)

# step3: 保存结果
movie_df.printSchema()
movie_df.show()

 

指定列名称转换
# toDF函数
# 将元素类型为元组类型的RDD直接转换为DataFrame
# def toDF(self: RDD[RowLike], schema: List[str]) -> DataFrame


# step1: 读取数据
# 用RDD方式进行读取
movie_rdd_str = spark.sparkContext.textFile("../data")

# step2: 处理数据
"""自定义Schema:自己定义RDD中数据对应的Schema"""
# a.将str类型的RDD变成Row类型的RDD
movie_rdd_list = ( movie_rdd_str
                  # 先将每个字符串分割,变成列表
                  .map(lambda line: re.split("\\s+", line))
                  # 将每个列表转换成一条Row类型对象数据
                  .map(lambda item: (item[0], item[1], float(item[2]), int(item[3])) )
)

# b.将RDD转换成DF
movie_df = movie_rdd_list.toDF(["userid", "movieid", "rate", "ts"])

# step3: 保存结果
movie_df.printSchema()
movie_df.show()

DataFrame的使用

SQL风格

#1.把DF注册为一个视图(表)
createOrReplaceTempView()

#2.写SQL
spark.sql("这里就是写SQL的地方")


DSL风格

(1)SQL中的关键字
(2)RDD算子
(3)pyspark包下,导包的方式:import pyspark.sql.functions as F


# Catalyst优化器
不论是SQL还是DSL,只要计算的逻辑是一样的,经过优化器,最终的实现也是一样的
所以相同执行逻辑的代码性能上没有区别
wordcount案例
# 数据源 word.txt

hadoop hive hadoop hive sqoop
sqoop hive hadoop kafka
sqoop kafka hbase hue
hadoop sqoop oozie
from pyspark.sql import SparkSession
import os
import pyspark.sql.functions as F

# 1.构建SparkSession
# 建造者模式:类名.builder.配置…….getOrCreate()
# 自动帮你构建一个SparkConf对象,只要指定你需要哪些配置就可
#SparkSQL:200
#SparkCore:最终由文件的切片数决定。
#最终调整策略:设置为核心数的2-3倍
spark = SparkSession \
    .builder \
    .master("local[2]")\
    .appName("SparkSQLAppName") \
    .config("spark.sql.shuffle.partitions", 4) \
    .getOrCreate()

# 2.数据输入
#会把文件内容的每一行当做一个value值
input_df = spark.read.text(paths='../data/word.txt')

# 3.数据处理
#3.1用SQL实现
input_df.createOrReplaceTempView("t1")
result_df1 = spark.sql("""
select word,count(word) as cnt 
from 
    (select explode(split(value,' ')) as word 
    from t1) t2
group by word
""")

#3.2 用DSL实现
result_df2 = input_df\
    .select(F.explode(F.split(input_df['value'],' ')).alias('word'))\
    .groupBy("word")\
    .count().alias("cnt")

result_df3 = input_df\
    .select(F.split('value',' ').alias("words"))\
    .select(F.explode('words').alias('word'))\
    .groupBy("word")\
    .agg(F.count("word").alias('cnt'))


# 4.数据输出
print("-------1.------")
input_df.printSchema()
input_df.show(truncate=False)
print("-------2.------")
result_df1.printSchema()
result_df1.show(truncate=False)
print("-------3.------")
result_df2.printSchema()
result_df2.show(truncate=False)
print("-------4.------")
result_df3.printSchema()
result_df3.show(truncate=False)
# 5.关闭SparkSession
spark.stop()

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值