SparkSQL概述以及创建Dataset

一、概述

http://spark.apache.org/docs/latest/sql-programming-guide.html

Spark SQL是Spark中一个模块,用以对结构化数据进行处理。SparkSQL在RDD之上抽象出来Dataset/Dataframe 这两个类提供了类似RDD的功能,也就意味用户可以使用map、flatMap、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.sparkgroupId>
    <artifactId>spark-core_2.11artifactId>
    <version>2.4.4version>
dependency>
<dependency>
    <groupId>org.apache.sparkgroupId>
    <artifactId>spark-sql_2.11artifactId>
    <version>2.4.4version>
dependency>

开发应用

package com.baizhi.sql

import org.apache.spark.sql.SparkSession

/**
  * 第一个spark sql的单词计数案例
  *
  */
object SparkSQLWordCount {
  def main(args: Array[String]): Unit = {
    // 1. sparkSession是spark sql应用入口,内部封装了sparkconf和sparkContext
    val spark = SparkSession
      .builder()
      .appName("the first spark sql example")
      .master("local[*]")
      .getOrCreate()

    // 2. 创建Dataset
    val rdd = spark.sparkContext.makeRDD(List("Hello Hadoop", "Hello Scala")).flatMap(_.split(" ")).map((_, 1))
    // 3. rdd ==> Dataset
    // 4. 导入隐式转换
    import spark.implicits._
    val dataset = rdd.toDS // (Hello 1) | (Hadoop 1)

    // 5. 对dataset进行sql处理
    dataset
      .where("_1 !='Scala'")
      .groupBy("_1")
      .sum("_2")
      .withColumnRenamed("_1", "word")
      .withColumnRenamed("sum(_2)", "num")
      .show()
    /*
    +------+-------+
    |    _1|sum(_2)|
      +------+-------+
    | Hello|      2|
    | Scala|      1|
    |Hadoop|      1|
    +------+-------+
    */

    //------------------------------------------------------------------------------
    val dataFrame = dataset.toDF()
    dataFrame.createOrReplaceTempView("t_word")
    dataFrame.sqlContext.sql("select _1 as word, count(_2) as num from t_word group by _1").show()
    /*
    +------+---+
    |  word|num|
    +------+---+
    | Hello|  2|
    | Scala|  1|
    |Hadoop|  1|
    +------+---+
     */
    // 6. 关闭spark sql应用
    spark.stop()
  }
}

三、创建数据源

创建Dataset

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

样例类创建

// 通过样例类创建dataset
val userList = List(User(1, "zs", true), User(2, "ls", false), User(3, "ww", true))
import spark.implicits._
val dataset = userList.toDS // 通过样例类构建的dataset字段名是样例类属性名
dataset.show()

//-----------------------------------------------
+---+----+-----+
| id|name|  sex|
+---+----+-----+
|  1|  zs| true|
|  2|  ls|false|
|  3|  ww| true|
+---+----+-----+

Tuple创建

// 通过元组创建dataset
val tupleList = List((1, "zs", true), (2, "ls", false), (3, "ww", true))
import spark.implicits._
val dataset = tupleList.toDS
dataset.show()
//-----------------------------------------------
+---+---+-----+
| _1| _2|   _3|
+---+---+-----+
|  1| zs| true|
|  2| ls|false|
|  3| ww| true|
+---+---+-----+

JSON创建

// 通过JSON创建
val dataset = spark.read.json("file:///G:\\IDEA_WorkSpace\\scala-workspace\\spark-day7\\src\\main\\resources").as("user")
//-----------------------------------------------
+---+----+-----+
| id|name|  sex|
+---+----+-----+
|  4| zs2| true|
|  5| ls2|false|
|  6| ww2| true|
|  1|  zs| true|
|  2|  ls|false|
|  3|  ww| true|
+---+----+-----+

RDD创建

// 通过RDD【元组集合】创建
val rdd = spark.sparkContext.makeRDD(List((1, "zs", true), (2, "ls", false), (3, "ww", true)))
import spark.implicits._
val dataset = rdd.toDS
dataset.show()

// 通过RDD【样例类集合】创建
val rdd = spark.sparkContext.makeRDD(List(User(1, "zs", true), User(2, "ls", false), User(3, "ww", true)))
import spark.implicits._
val dataset = rdd.toDS
dataset.show()

创建Dataframe

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

Json创建

// 通过JSON创建
val df = spark.read.json("file:///G:\\IDEA_WorkSpace\\scala-workspace\\spark-day7\\src\\main\\resources")
df.printSchema()  // df结构
df.show()
//-------------------------------------------------------------------
root
 |-- id: long (nullable = true)
 |-- name: string (nullable = true)
 |-- sex: boolean (nullable = true)

+---+----+-----+
| id|name|  sex|
+---+----+-----+
|  4| zs2| true|
|  5| ls2|false|
|  6| ww2| true|
|  1|  zs| true|
|  2|  ls|false|
|  3|  ww| true|
+---+----+-----+

样例类创建

val userDF=List(User2(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创建

// RDD【元组】转换创建
val rdd = spark.sparkContext.makeRDD(List((1,"zs"),(2,"ls")))
val df = rdd.toDF("id","name")
df.printSchema()
df.show()
//--------------------------------------------------------------------
root
 |-- id: integer (nullable = false)
 |-- name: string (nullable = true)

+---+----+
| id|name|
+---+----+
|  1|  zs|
|  2|  ls|
+---+----+

// RDD【样例类】转换创建
var userDF= spark.sparkContext.parallelize(List(User(1,"zs",true))).toDF("id","uname","sex") 
userDF.show()
//--------------------------------------------------------------------
+---+-----+----+
| id|uname| sex| 
+---+-----+----+
| 1 | zs  |true| 
+---+-----+----+

// 通过RDD[Row]创建DF
val rdd = spark.sparkContext.parallelize(List((1, "zs", true), (2, "ls", false))).map(t => Row(t._1, t._2, t._3))
val schema = new StructType()
    .add("id", IntegerType)
    .add("name", StringType)
    .add("sex", BooleanType)
val df = spark.createDataFrame(rdd, schema)
df.show()
spark.stop()
//--------------------------------------------------------------------
+---+----+-----+
| id|name|  sex|
+---+----+-----+
|  1|  zs| true|
|  2|  ls|false|
+---+----+-----+

// 通过JAVA Bean创建DF
val personList = List(new Person(1, "zs"), new Person(2, "ls"))
val rdd = spark.sparkContext.makeRDD(personList)
val df = spark.createDataFrame(rdd, classOf[Person])
df.show()
//--------------------------------------------------------------------
+---+----+
| id|name|
+---+----+
|  1|  zs|
|  2|  ls|
+---+----+

// 通过RDD[case class]创建DF
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|
+---+----+----+

// 通过RDD[Tuple] 创建DF
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| 
+---+---+----+

你可能感兴趣的:(#,Spark)