sparkSql的使用

本文深入探讨Apache Spark SQL,介绍其核心组件Dataset和DataFrame,提供快速入门指导,涵盖创建、操作和查询数据的方法,包括数据加载、保存、SQL查询、自定义函数及聚合函数等高级特性,旨在帮助开发者提升数据处理效率。
摘要由CSDN通过智能技术生成

Apache Spark SQL

Spark SQL是构建在RDD之上的ETL(Extract Transform Load)工具。SparkSQL在RDD之上抽象出来Dataset/Dataframe这两个类提供了类似RDD的功能,也就意味用户可以使用map、faltMap、filter等高阶算子,同时也通过了基于列的命名查询,也就是说Dataset/DataFrame提供了两套操作数据的API,这些API可以给Saprk引擎要提供更多信息,系统可可以根据这些信息对计算实现一定的优化。目前Spark SQL提供了两种交互方式1)SQL 脚本 2)Dataset API(strong-typed类型、untyped类型操作)

Datasets & DataFrames

Dataset是一个分布式数据集,Dataset是在spark-1.6提出新的API,该API构建在RDD(strong type,使用lambda表达式)之上同时可以借助于Spark SQL对执行引擎的优点,使得使用Dateset执行一些数据的转换比直接使用RDD算子功能和性能都有所提升。因此我们可以认为Dateset就是一个加强版本的RDD。Dataset除了可以使用JVM中数组|集合对象创建之外,也可以将任意的一个RDD转换为Dataset.Python does not have the support for the Dataset API.

DataFrames 是Dataset的一种特殊情况。比如 Dataset中可以存储任意 对象类型的数据作为Dataset的元素。但是Dataframe的元素只有一种类型Row类型,这种基于Row查询和传统数据库中ResultSet操作极其相似。因为Row类型的数据表示Dataframe的一个元素,类似数据库中的一行,这些行中的元素可以通过下标或者column name访问。由于 Dateset是API的兼容或者支持度上不是多么的好,但是Dataframe在API层面支持的Scala、Java、R、Python支持比较全面。

快速入门

  • 引入依赖
<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-core_2.11</artifactId>
    <version>2.4.3</version>
</dependency>
<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-sql_2.11</artifactId>
    <version>2.4.3</version>
</dependency>
  • 创建字符统计(untyped)
//1.创建SparkSeesion
val spark=SparkSession.builder()
    .appName("wordcount")
    .master("local[6]")
    .getOrCreate()

//2.导入spark定义隐式增强|转换
import spark.implicits._

//3.创建dataset
val lines=Array("this is a demo","hello spark")
val wordRDD = spark.sparkContext.makeRDD(lines)
.flatMap(_.split("\\s+"))
.map((_,1))

val ds:Dataset[(String,Int)]=wordRDD.toDS()
//4.对Dataset执行sql算子操作
ds.groupBy($"_1") //无类型操作
    .sum("_2").as("total")
    .withColumnRenamed("_1","word")
    .withColumnRenamed("sum(_2)","total")
    .show()

//5.关闭spark
spark.stop()
  • 创建字符统计(strong typed)
//1.创建SparkSeesion
val spark=SparkSession.builder()
    .appName("wordcount")
    .master("local[6]")
    .getOrCreate()

//2.导入spark定义隐式增强|转换
import spark.implicits._

//3.创建dataset
val lines=Array("this is a demo","hello spark")
val wordRDD = spark.sparkContext.makeRDD(lines)
    .flatMap(_.split("\\s+"))
    .map((_,1))

val ds:Dataset[(String,Int)]=wordRDD.toDS()
//4.对Dataset执行sql算子操作
ds.groupByKey(t=>t._1)
    .agg(typed.sum[(String,Int)](tuple=>tuple._2).name("total"))
    .show()

//5.关闭spark
spark.stop()

Dataset & Dataframe

Dataset create

Dataset类似于RDD,不同的是Spark SQL有一套自己的序列化规范独立于Spark RDD(Java/Kryo序列化)之上称为Encoders。不同于SparkRDD序列化,由于Dataset支持无类型操作,用户无需获取操作的类型,操作仅仅是列名,因为Spark SQL在执行算子操作的时候可以省略反序列化的步骤,继而提升程序执行效率。

  • case-class
case class Person(id:Int,name:String,age:Int,sex:Boolean)

val person: Dataset[Person] =List(Person(1,"zhangsan",18,true),Person(2,"wangwu",28,true)).toDS()
person.select($"id",$"name")
.show()
+---+--------+
| id|    name|
+---+--------+
|  1|zhangsan|
|  2|  wangwu|
+---+--------+
  • Tuple元组
val person: Dataset[(Int,String,Int,Boolean)] =List((1,"zhangsan",18,true),(2,"wangwu",28,true)).toDS()
person.select($"_1",$"_2")
.show()
+---+--------+
| _1|      _2|
+---+--------+
|  1|zhangsan|
|  2|  wangwu|
+---+--------+
  • json数据
{
   "name":"张三","age":18} 
{
   "name":"lisi","age":28} 
{
   "name":"wangwu","age":38}
case class User(name:String,age:Long)//数值默认是long类型
spark.read.json("file:///D:/demo/json/").as[User]
        .show()
+---+------+
|age|  name|
+---+------+
| 18|  张三|
| 28|  lisi|
| 38|wangwu|
+---+------+
  • rdd

    • 元组
    val userRDD = spark.sparkContext.makeRDD(List((1,"张三",true,18,15000.0)))
    userRDD.toDS().show()
    
    +---+----+----+---+-------+
    | _1|  _2|  _3| _4|     _5|
    +---+----+----+---+-------+
    |  1|张三|true| 18|15000.0|
    +---+----+----+---+-------+
    
    • case-class
    val userRDD = spark.sparkContext.makeRDD(List(Person(1,"张三",18,true)))
    userRDD.toDS().show()
    
    +---+----+---+----+
    | id|name|age| sex|
    +---+----+---+----+
    |  1|张三| 18|true|
    +---+----+---+----+
    

Dataframe create

DataFrame是一个命名列的数据集,用户可以直接操作column因此几乎所有Dataframe推荐操作都是无类型操作。用户也可以把一个Dataframe看做是Dataset[Row]类型的数据集。

  • json文件
val dataFrame:DataFrame = spark.read.json("file:///D:/demo/json")
dataFrame.printSchema()
dataFrame.show()
  • case-class
case class User(id:Int,name:String,sex:Boolean)

var userDF=List(User(1,"zs",true)).toDF()
userDF.show()
+---+----+----+
| id|name| sex|
+---+----+----+
|  1|  zs|true|
+---+----+----+
  • Tuple元组
var userDF=List((1,"zs",true)).toDF("id","name","sex")
userDF.show()
+---+----+----+
| id|name| sex|
+---+----+----+
|  1|  zs|true|
+---+----+----+
  • RDD转换

    • 元组
    var userDF= spark.sparkContext.parallelize(List((1,"zs",true)))
    .toDF("id","name","sex") //可以指定列
    userDF.show()
    
    +---+----+----+
    | id|name| sex|
    +---+----+----+
    |  1|  zs|true|
    +---+----+----+
    
    • case-class
    var userDF= spark.sparkContext.parallelize(List(User(1,"zs",true)))
    .toDF("id","uname","sex")
    userDF.show()
    
    +---+-----+----+
    | id|uname| sex|
    +---+-----+----+
    |  1|   zs|true|
    +---+-----+----+
    
    • RDD[Row]类型转为DataFrame
    var userRDD:RDD[Row]= spark.sparkContext.parallelize(List(User(1,"zs",true)))
    	.map(u=>Row(u.id,u.name,u.sex))
    
    var schema=new StructType()
        .add("id",IntegerType)
        .add("name",StringType)
        .add("sex",BooleanType)
    
    var userDF=spark.createDataFrame(userRDD,schema)
    userDF.show()
    
    +---+----+----+
    | id|name| sex|
    +---+----+----+
    |  1|  zs|true|
    +---+----+----+
    
    • Javabean
    public class JavaUser implements Serializable {
         
        private Integer id;
        private String name;
        private Boolean sex;
       // get/set
    }
    
    var userRDD:RDD[JavaUser]=spark.sparkContext.makeRDD(List(new JavaUser(1,"zs",true)))
    var userDF=spark.createDataFrame(userRDD,classOf[JavaUser])
    userDF.show()
    
    • case-class
    case class ScalaUser(id:Int,name:String,sex:Boolean)
    
    var userRDD:RDD[ScalaUser]=spark.sparkContext.makeRDD(List(ScalaUser(1,"zs",true)))
    var userDF=spark.createDataFrame(userRDD)
    userDF.show()
    
    +---+----+----+
    | id|name| sex|
    +---+----+----+
    |  1|  zs|true|
    +---+----+----+
    
    • 元组
    var userRDD:RDD[(Int,String,Boolean)]=spark.sparkContext.makeRDD(List((1,"zs",true)))
    var userDF=spark.createDataFrame(userRDD)
    userDF.show()
    
    +---+---+----+
    | _1| _2|  _3|
    +---+---+----+
    |  1| zs|true|
    +---+---+----+
    

##DataFrame Operati

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值