当前位置:   article > 正文

【Spark】SparkSQL入门解析(一)_sparksql语法

sparksql语法

在这里插入图片描述

【一】简介 (本文部分图片来自网络,侵删)

Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象叫做DataFrame并且作为分布式SQL查询引擎的作用

在这里插入图片描述

【二】特点

【2.1】易整合

Spark SQL可以使用SQL或熟悉的DataFrame API在Spark程序中查询结构化数据,可在Java,Scala,Python和R中使用

在这里插入图片描述

【2.2】统一的数据访问方式

DataFrame和SQL提供了一种访问各种数据源的通用方法,包括Hive,Avro,Parquet,ORC,JSON和JDBC。甚至可以跨这些源联接数据

在这里插入图片描述

【2.3】兼容Hive

Spark SQL支持HiveQL语法以及Hive SerDes和UDF,从而访问现有的Hive仓库

在这里插入图片描述

【2.4】标准的数据连接

服务器模式为商业智能工具提供了行业标准的JDBC和ODBC连接
在这里插入图片描述


【三】概述

【3.1】SparkSQL可以看做是一个转换层,向下对接各种不同的结构化数据源,向上提供不同的数据访问方式

在这里插入图片描述


【3.2】
在SparkSQL中Spark为我们提供了两个新的抽象,分别是DataFrame和DataSet;他们和RDD有什么区别呢?首先从版本的产生上来看:RDD (Spark1.0) —> Dataframe(Spark1.3) —> Dataset(Spark1.6)
如果同样的数据都给到这三个数据结构,他们分别计算之后,都会给出相同的结果。不同是的他们的执行效率和执行方式
注意:在后期的Spark版本中,DataSet会逐步取代RDD和DataFrame成为唯一的API接口

在这里插入图片描述

【3.3】RDD
RDD概述
  • 【1】RDD意为弹性分布式数据集,是一个懒执行的、不可变的可以支持Lambda表达式的并行数据集合
  • 【2】RDD的最大好处就是简单,API的人性化程度很高
  • 【3】RDD的劣势是性能限制,它是一个JVM驻内存对象,这也就决定了存在GC的限制和数据增加时Java序列化成本的升高
【3.4】DataFrame
DataFrame概述
  • 【1】与RDD类似,DataFrame也是一个分布式数据数据集。然而DataFrame更像传统数据库的二维表格,除了数据以外,还记录数据的结构信息,即Schema信息
  • 【2】与Hive类似,DataFrame也支持嵌套数据类型(struct、array和map)
  • 【3】从API易用性的角度上看,DataFrame API提供的是一套高层的关系操作,比函数式的RDD API要更加友好,门槛更低。由于与R和Pandas的DataFrame类似,Spark DataFrame很好地继承了传统单机数据分析的开发体验
    在这里插入图片描述
  • 【1】上图直观地体现了DataFrame和RDD的区别。左侧的RDD[Person]虽然以Person为类型参数,但Spark框架本身不了解Person类的内部结构。而右侧的DataFrame却提供了详细的结构信息,使得Spark SQL可以清楚地知道该数据集中包含哪些列,每列的名称和类型各是什么。DataFrame多了数据的结构信息,即Schema。RDD是分布式的Java对象的集合,DataFrame是分布式的Row对象的集合。DataFrame除了提供了比RDD更丰富的算子以外,更重要的特点是提升执行效率减少数据读取以及执行计划的优化,比如filter下推、裁剪等…
  • 【2】DataFrame是为数据提供了Schema的视图,可以把它当做数据库中的一张表来对待
  • 【3】DataFrame也是懒执行的,性能上比RDD要高,主要有两方面原因:
    ①.定制化内存管理
    ②.数据以二进制的方式存在于非堆内存,节省了大量空间之外,还摆脱了GC的限制
    在这里插入图片描述
  • 【1】优化的执行计划 ,查询计划通过Spark catalyst optimiser进行优化

在这里插入图片描述

  • 【2】比如下面一个例子
    在这里插入图片描述
    在这里插入图片描述
  • 【3】为了说明查询优化,我们来看上图展示的人口数据分析的示例。图中构造了两个DataFrame,将它们join之后又做了一次filter操作。如果原封不动地执行这个执行计划,最终的执行效率是不高的。因为join是一个代价较大的操作,也可能会产生一个较大的数据集
    如果我们能将filter下推到 join下方,先对DataFrame进行过滤,再join过滤后的较小的结果集,便可以有效缩短执行时间。而Spark SQL的查询优化器正是这样做的。简而言之,逻辑查询计划优化就是一个利用基于关系代数的等价变换,将高成本的操作替换为低成本操作的过程
    得到的优化执行计划在转换成物理执行计划的过程中,还可以根据具体的数据源的特性将过滤条件下推至数据源内。最右侧的物理执行计划中Filter之所以消失不见,就是因为溶入了用于执行最终的读取操作的表扫描节点内
    对于普通开发者而言,查询优化器的意义在于,即便是经验并不丰富的程序员写出的次优的查询,也可以被尽量转换为高效的形式予以执行
  • 【6】DataFrame的劣势在于在编译期缺少类型安全检查,导致运行时出错
【3.5】DataSet
DataSet概述
  • 【1】DataSet是Dataframe API的一个扩展,是Spark最新的数据抽象
  • 【2】DataSet用户友好的API风格,既具有类型安全检查也具有DataFrame的查询优化特性
  • 【3】DataSet支持编解码器,当需要访问非堆上的数据时可以避免反序列化整个对象,提高了效率
  • 【4】样例类被用来在DataSet中定义数据的结构信息,样例类中每个属性的名称直接映射到DataSet中的字段名称
  • 【5】DataFrame和DataSet之间可以互相转换,DataFrame/DataSet[Row] + 类型 =DataSet [类型] ,所以可以通过 as 方法将DataFrame转换为DataSet,也可以通过 toDF 方法将DataSet转换为DataFrame
  • 【6】DataSet是强类型的,比如可以有DataSet[Car],DataSet[Person]…

DataFrame只是知道字段,但是不知道字段的类型,所以在执行这些操作的时候是没办法在编译的时候检查是否类型失败的,比如你可以对一个String进行减法操作,在执行的时候才报错,而DataSet不仅仅知道字段,而且知道字段类型,所以有更严格的错误检查。就跟JSON对象和类对象之间的类比,如下图:
在这里插入图片描述

注意:RDD让我们能够决定怎么做,而DataFrame和DataSet让我们决定做什么,控制的粒度不一样

在这里插入图片描述

【3.6】RDD、DataFrame和DataSet三者的共性
  • 【1】RDD、DataFrame、DataSet全都是Spark平台下的分布式弹性数据集,为处理超大型数据提供便利
  • 【2】三者都有惰性机制,在进行创建、转换,如map方法时,不会立即执行,只有在遇到Action如foreach时,三者才会开始遍历运算,极端情况下,如果代码里面有创建、转换,但是后面没有在Action中使用对应的结果,在执行时会被直接跳过
	val sparkconf = new SparkConf().setMaster("local[*]").setAppName("sparkSqlDemo")
	val spark = SparkSession.builder().config(sparkconf).getOrCreate()
	val rdd = spark.sparkContext.parallelize(Seq(("a", 1), ("b", 1), ("a", 1)))
	// 下面这个map并不会运行
	rdd.map{line=>
	  println("运行到这里啦...")
	  line._1
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 【3】三者都会根据Spark的内存情况自动缓存运算,这样即使数据量很大,也不用担心会内存溢出
  • 【4】三者都有partition的概念
  • 【5】三者有许多共同的函数,如filter,排序等…
  • 【6】在对DataFrame和DataSet进行操作许多操作都需要导入下方隐式函数的支持
注意:spark不是包名,是SparkSession的名字
import spark.implicits._
  • 1
  • 2
  • 【7】DataFrame和DataSet均可使用模式匹配获取各个字段的值和类型

DataFrame:

	df.map {
		case Row(id: Int, name: String, age: Int) => {
		   println(s"${id},${name},${age}")
		   name
		 }
		 case _ => ""
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

DataSet:

	ds.map {
		 case User(id: Int, name: String, age: Int) => {
		    println(s"${id},${name},${age}")
		    name
		  }
		  case _ => ""
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
【3.7】RDD、DataFrame和DataSet三者的区别
【1】RDD:
RDD可以设置类型参数,但RDD并不了解其内部结构
  • 1
【2】DataFrame:
1.与RDD和DataSet不同,DataFrame每一行的类型固定为Row,只有通过解析才能获取各个字段的值,如下:       本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/767049
推荐阅读
相关标签