Spark学习之路——7.Spark SQL

一、Spark SQL简介

1.背景

(1)HiveQL是将SQL语句转化为了MapReduce作业来执行,当使用Spark来代替MapReduce计算时,就变成了Hive on Spark(Shark),实现了将HiveQL翻译成Spark上的RDD操作。

(2)Shark一方面提高了SQL on Hadoop的性能,但是也导致了两个问题:①执行计划完全依赖于Hive;②Spark是线程级的,但是MapReduce是进程级的,所以导致Spark在兼容Hive的实现上存在线程安全问题,所以Shark也要维护一套打了补丁的Hive源码分支。

(3)2014年6月1日Shark项目和Spark SQL项目的主持人Reynold Xin宣布:停止对Shark的开发,团队将所有资源放在Spark SQL项目上,至此,Shark的发展画上了句话,但也因此发展出两个直线:Spark SQL和Hive on Spark。

    ①Spark SQL作为Spark生态的一员继续发展,而不再受限于Hive,只是兼容Hive。

    ②Hive on Spark是一个Hive的发展计划,该计划将Spark作为Hive的底层引擎之一,也就是说,Hive将不再受限于一个引擎,可以采用Map-Reduce、Tez、Spark等引擎。

二、Spark SQL主要内容

SparkSQL成为了专门处理结构化数据(比如DB,Json)的Spark组件

SparkSQL=Schema+RDD

1.Spark SQL架构

(1) Spark SQL在Hive兼容层面仅依赖HiveQL解析。

(2) Spark SQL执行计划的生成和优化都由Catays(函数式关系查询优化框架)负责

(3) Spark SQL底层基于Spark Core(RDD)

2.DataFrame(基于RDD)

DataFrame是以RDD为基础的分布式数据集,提供了详细的结构信息(RDD+Schema)。

DataFrame的推出,让Spark具备处理大规模结构化数据的能力,且比RDD方式更简单易用,而且具有更高的计算性能。

(1)创建DataFrame

通过已存在的RDD创建DataFrame、通过读取Hive表来创建DataFrame、其他数据源中创建DataFrame、由其他DataFrame转换而来。

spark 2.x后开始加入使用SparkSeesion。

提供了读写各种格式数据的API

 

(2)DataFrame小结

采用更高效的数据格式保存数据

使用列式存储格式(比如parquet)

使用分区(比如/year=2014/month=02/…)

使用统计数据自动跳过数据(比如min、max)

 

(3)数据的列式存储方式

parquet和orc

①可以跳过不符合条件的数据,只读取需要的数据,降低IO数据量

②压缩编码可以降低磁盘存储空间,进一步节约存储空间。

③只读取需要的列,支持向量运算,具备更好的扫描性能。

 

3.Spark SQL的性能

核心优化器:Catalyst

作用是将逻辑计划和物理计划的两次调用调优为一次调用

 

4.Dataset

扩展自DataFrame API(函数式编程风格、运行时检查、不能直接操作domain对象),提供了编译时类型安全,面向对象风格的API。

Dataset类型安全,可以直接作用于domain对象,在编译时进行类型检查,可以和DataFrame互相转换。

从范围上看DataSets是RDD和DataFrame的超集

 

三、Spark SQL的简单应用

1.程序设计过程(此处只以计算FG% : 投篮命中率为例)

(1)创建SparkSession

import org.apache.spark.sql.{SQLContext, SparkSession}
object Z_score {
  // (1) 分析2016年 ① ② ③ ④ 属性 z-score 排名
  //用来分析的指标 ① FG% : 投篮命中率,② FT% :罚球命中率  ③ 3P: 三分球命中率  ④ TRB: 篮板球
  def main(args: Array[String]): Unit = {
    val ss=SparkSession.builder
      .master("local")
      .appName("Z-score")
      .config("spark.debug.maxToStringFields", "100")
      .config("spark.sql.crossJoin.enabled","true")//SparkSql不支持笛卡尔积操作,所以在这里要设置一下
      .getOrCreate()
    val datapath="hdfs://master:9000/user/spark/data/basketball/leagues_NBA_2016_per_game_per_game.csv"
    //读取2016年数据到dataframe中
    var playerdata=ss.read.format("csv")
      .option("header",true)//文件有表头
      .option("inferSchema",true.toString)//自动推断属性列的数据类型
      .load(datapath)
      .na.fill(0)//将null值均用0补齐
    //选择需要的数据
    playerdata=playerdata.select("Rk","Player","Age","FG%","3P13","FT%","TRB")
    playerdata=playerdata.withColumnRenamed("FG%","FGrate")
    playerdata=playerdata.withColumnRenamed("FT%","FTrate")

(2)创建DataFrame或DataSet

(3)在DataFrame或DataSet上进行转换或action操作

//①FG%
计算所有球员该数据均值
val calmeanFG=playerdata.agg("Rk"->"max","FG%"->"sum")
var meanFG=calmeanFG.select(calmeanFG("sum(FG%)")/calmeanFG("max(Rk)"))
meanFG=meanFG.withColumnRenamed("(sum(FG%) / max(Rk))","meanFG%")
    //作笛卡尔积操作(将均值和标准差添加入dataframe中便于操作)
var fg=playerdata.join(FGdata)
    fg=fg.select(fg("Player"),fg("Age"),(fg("FGrate")-fg("meanFG"))/fg("stdFG"))
    fg=fg.sort(-fg("((FGrate - meanFG) / stdFG)")).withColumnRenamed("((FGrate - meanFG) / stdFG)","z_FG")
    fg.show(10)

(4)然后返回结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值