[Spark]-结构化数据查询详解

1.概述

  Spark-SQL是Spark用于处理结构化数据的一个模块.

  它与RDD的优势在于

    对外而言,类SQL语言会有更大的人群适应性.

    对内而言,Spark-SQL的结构化信息,会带来额外的执行优化

  注意一个认识误区,Spark-SQL 不等于 SQL.

    Spark-SQL是Spark用于处理结构化数据的一个模块,SQL仅仅只是Spark-SQL中一部分,而在SQL之外,Spark还有DataFrame,DataSet等等,也是Spark用来处理结构化数据的技术手段

2.Spark的结构化数据处理方案

  2.1 dataset

     dataset是Spark自1.6+版本后添加一种新的分布式数据集.类似与一个强类型的分布式的Java集合

     它的目的为传统RDD增加结构化(强类型)的支持,依赖更多的来自结构化的信息,为执行计划提供更好的优化.

   2.2 dataframe

    dataframe是dataset<Row>的别名,它是用统一的Row对象(包含列名,数据类型等等)作为强类型的包装,类似与关系型数据库的表概念.

    dataframe相比dataset,在面对外部数据源时会更加方便(不用写强类型定义),比如结构化数据文件等等

  2.3 SQL

    Spark对结构化查询语言(SQL)处理结构化数据的支持.并且完美兼容HiveSQL(事实上,Spark甚至内置了一个Hive引擎)

  这三种只是针对开发者而言的技术手段区分,事实上Spark内部是使用同一种计算引擎处理的.换句话说,我们可以在这三种技术手段之间自由的切换

2.SparkSession

  SparkSession 是 Spark-SQL的统一入口.一个简单的SparkSession声明如下  

  import org.apache.spark.sql.SparkSession

  val spark = SparkSession
    .builder()
    .getOrCreate()

  // For implicit conversions like converting RDDs to DataFrames
  import spark.implicits._

3.DataFrames

 

import org.apache.spark.sql.SparkSession;

  val spark = SparkSession
    .builder()
    .appName("Spark-Sql-DataFrame-App").master("local[2]")
    .getOrCreate();
  import spark.implicits._;

  /**
    * 构建一个DF
    *   读取一个本地Json文件(可以是HDFS或任意Hadoop支持的存储系统)
    */
  val peopleDF =  spark.read.json("D:\\data\\people.json");

  /**
    * DF的一些基本操作
    */
  println("******************************** DF的一些基本操作 *************************************")
  //打印架构
  peopleDF.printSchema()
  //打印前10行数据
  peopleDF.show(10)
  //dataFrame依然有RDD的支持(比如持久化机制)
  val peopleCache = peopleDF.filter($"age">0).cache();
  //一个简单的dataFrame查询实例
  peopleCache.filter($"age"< 30).select($"name",$"age").groupBy($"name",$"age").count().show(10)


  /**
    * DF转SQL的临时表
    * 这样可以非常容易的将一个DF转到SQL层面来处理
    */
  println("******************************** DF转SQL *************************************")
  //类似RDBMS的会话临时表,SparkSession关闭后自动关闭临时表
  peopleCache.createOrReplaceTempView("peopleTmp")
  spark.sql("select name,age,count(1) from peopleTmp where age < 30 group by name,age").show(10)
  //类似RDBMS的全局临时表,可以在跨Session状态下使用
  //全局临时表必须注册在global_temp,且使用时必须包含全名: global_temp.xxxx
  peopleCache.createOrReplaceGlobalTempView("peopleGlobTmp")
  spark.newSession().sql("select name,age,count(1) from global_temp.peopleGlobTmp where age < 30 group by name,age").show(10)

  spark.close();

 4.DataSet 

  import org.apache.spark.sql.SparkSession;

  val spark = SparkSession
    .builder()
    .appName("Spark-Sql-DataSet-App").master("local[2]")
    .getOrCreate();

  import spark.implicits._;

  //定义描述DS结构的Person类型
  case class Person(name: String, age: Long)

  /**
    * 构建DS
    */
  //从一个Java对象集合中创建DS
  val dsFromScalaCollection = Seq(Person("SuperMan", 20)).toDS();
  //从一个结构化的外部系统中创建DS
  val dsFromLocalSystem_Json = spark.read.format("json").load("D:\\data\\people.json").na.fill(0,Seq("age")).as[Person];
  //从一个非结构化的外部数据源中创建DS
  val dsFromLocalSystem_Txt = spark.read.textFile("D:\\data\\people.txt")
    .map(line => line.split(",")).map(columns => Person(columns(0), columns(1).trim.toInt))
  //使用unionByName而不使用union  union:根据模式中的位置解析列(模式中的列位置不一定与数据集中强类型对象中的字段匹配)
  val peopleDS = dsFromScalaCollection.unionByName(dsFromLocalSystem_Txt).unionByName(dsFromLocalSystem_Json)

  //数据任意使用,不关心来自什么外部系统(外部系统异构透明)
  peopleDS.filter($"age"< 30).select($"name",$"age").groupBy($"name",$"age").count().show(10)

  spark.stop()

5.Sql

  val spark = SparkSession.builder().appName("SQL-App").master("local[2]").getOrCreate()
  import  spark.implicits._;
  case class Person(name: String, age: Long)

  //DS读取非结构化数据至SQL临时表
  spark.read.textFile("D:\\data\\people.txt")
    .map(line=>line.split(",")).map(columns=>Person(columns(0),columns(1).trim.toLong))
    .createTempView("data_from_txt")

  //Sql方式读取数据
  val sql =
    """
      |CREATE TEMPORARY VIEW data_from_json
      |USING org.apache.spark.sql.json
      |OPTIONS (
      |  path "D:\\data\\people.json"
      |)
    """.stripMargin;
  spark.sqlContext.sql(sql);
  //简单使用
  spark.sqlContext.sql("SELECT * FROM  data_from_json json join data_from_txt txt on json.name = txt.name").show();

  spark.close();

猜你喜欢

转载自www.cnblogs.com/NightPxy/p/9259226.html