一, 简介

Spark SQL是用于结构化数据处理的Spark模块。与基本的Spark RDD API不同,Spark SQL提供的接口为Spark提供了关于数据结构和正在执行的计算的更多信息。在内部,Spark SQL使用这些额外的信息来执行额外的优化。有几种与Spark
SQL进行交互的方式,包括SQL和Dataset API。在计算结果时,使用相同的执行引擎,而不管使用哪种API /语言表示计算。这种统一意味着开发人员可以轻松地在不同的API之间来回切换,基于这些API提供了表达给定转换的最自然的方式。

Spark SQL的一个用途是执行SQL查询。Spark SQL也可以用来从现有的Hive安装中读取数据。从另一种编程语言中运行SQL时,结果将作为数据集/数据框返回。您还可以使用命令行 或通过JDBC / ODBC与SQL接口进行交互。

二, 数据集和数据框(Datasets and DataFrames)

数据集Datasets 是分布式数据集合。数据集Datasets 是Spark
1.6中添加的一个新接口,它提供了RDD(强类型,使用强大的lambda函数的功能)的好处以及Spark SQL优化执行引擎的优点。数据集可以被构造从JVM对象,然后使用功能性的转换操作(map,flatMap,filter等等)。数据集API可用于Scala和 Java。Python不支持数据集API。但是由于Python的动态特性,数据集API的许多优点已经可用(例如,您可以自然地通过名称访问行的字段 row.columnName)。R的情况类似。

      一个DataFrame是一个数据集组织成命名列。它在概念上等同于关系数据库中的表格或R / Python中的数据框架,但具有更丰富的优化。DataFrame可以从各种各样的源构建,例如:结构化数据文件,Hive中的表,外部数据库或现有的RDD。数据帧API是Scala,Java的,可用的Python和[R 。在Scala和Java中,DataFrame由Rows 的数据集表示。在Scala API中,DataFrame只是一个类型的别名Dataset[Row]。而在Java API中,用户需要Dataset<Row>用来表示一个DataFrame。

1,创建Spark Sql的入口

Spark中所有功能的入口点就是这个SparkSession类。要创建一个基本的SparkSession,只需使用SparkSession.builder():

import org.apache.spark.sql.SparkSession

val spark = SparkSession
.builder()
.appName("Spark SQL basic example")
.config("spark.some.config.option", "some-value")
.getOrCreate()
import spark.implicits._


  SparkSession在Spark
2.0中为Hive特性提供内置支持,包括使用HiveQL编写查询,访问Hive UDF以及从Hive表读取数据的能力。要使用这些功能,您不需要有现有的Hive安装程序。

2,创建数据框DataFrame

使用a SparkSession,应用程序可以从现有的RDD,Hive表或Spark数据源创建DataFrame 举个例子,下面根据JSON文件的内容创建一个DataFrame:

val df = spark.read.json("examples/src/main/resources/people.json")

// 显示数据框中的数据
df.show()
// +----+-------+
// | age| name|
// +----+-------+
// |null|Michael|
// | 30| Andy|
// | 19| Justin|
// +----+-------+

其中people.json中的数据为:

{"name":"Michael"}
{"name":"Andy", "age":30}
{"name":"Justin", "age":19}

3,无类型数据集Dataset操作(又名DataFrame操作) 

        DataFrames为Scala,Java,Python和R中的结构化数据操作提供了一个特定领域的语言。

        如上所述,在Spark 2.0中,DataFrames只是Row,Scala和Java API中的数据集。这些操作也被称为“无类型转换”,与强类型的Scala / Java数据集中的“类型转换”不同。这里我们包含一些使用数据集的结构化数据处理的基本示例:

 import spark.implicits._
// 以树形格式打印数据集的 Schema 格式
df.printSchema()
// root
// |-- age: long (nullable = true)
// |-- name: string (nullable = true) // 选择 name 的列数据
df.select("name").show()
// +-------+
// | name|
// +-------+
// |Michael|
// | Andy|
// | Justin|
// +-------+ // 选择所有的人,并且 age 加一,
df.select($"name", $"age" + 1).show()
// +-------+---------+
// | name|(age + 1)|
// +-------+---------+
// |Michael| null|
// | Andy| 31|
// | Justin| 20|
// +-------+---------+ // 选出年龄大于21的人信息
df.filter($"age" > 21).show()
// +---+----+
// |age|name|
// +---+----+
// | 30|Andy|
// +---+----+ // 通过年龄的升序排序,并计数每个人的数量
df.groupBy("age").count().show()
// +----+-----+
// | age|count|
// +----+-----+
// | 19| 1|
// |null| 1|
// | 30| 1|
// +----+-----+

有关可在数据集上执行的操作类型的完整列表,请参阅API文档

除了简单的列引用和表达式之外,数据集还具有丰富的函数库,包括字符串操作,日期算术,通用数学运算等等。DataFrame函数参考中提供了完整的列表。

4,以编程方式运行SQL查询

通过以上的例子利用sql函数,SparkSession使应用程序能够以编程方式运行SQL查询,并将结果返回为DataFrame。

    df.createOrReplaceTempView("people")  // 创建临时视图

    val sqlDF = spark.sql("SELECT * FROM people")
sqlDF.show()
// +----+-------+
// | age| name|
// +----+-------+
// |null|Michael|
// | 30| Andy|
// | 19| Justin|
// +----+-------+

5,全局临时视图

Spark SQL中的临时视图是会话范围的,如果创建它的会话终止,将会消失。如果您希望在所有会话之间共享一个临时视图并保持活动状态,直到Spark应用程序终止,则可以创建一个全局临时视图。全局临时视图与系统保存的数据库绑定global_temp,我们必须使用限定的名称来引用它,例如SELECT * FROM global_temp.view1。

   // 创建全局临时试图
df.createGlobalTempView("people") // 全局临时视图绑定到系统数据库中保存`global_temp` 
spark.sql("SELECT * FROM global_temp.people").show()
// +----+-------+
// | age| name|
// +----+-------+
// |null|Michael|
// | 30| Andy|
// | 19| Justin|
// +----+-------+ // 全局临时视图是跨会话的
spark.newSession().sql("SELECT * FROM global_temp.people").show()
// +----+-------+
// | age| name|
// +----+-------+
// |null|Michael|
// | 30| Andy|
// | 19| Justin|
// +----+-------+

6,创建数据集Dataset

      数据集类似于RDD,但是,不使用Java序列化或Kryo,而是使用专门的编码器对对象进行序列化以便通过网络进行处理或传输。虽然编码器和标准序列化都负责将对象转换为字节,但编码器是动态生成的代码,并且使用允许Spark执行许多操作(如过滤,排序和散列)的格式,而无需将字节反序列化回对象。

  case class Person(name: String, age: Long) // 强转类型
 import spark.implicits._
    // 自定义类//创建case类的编码器
    val caseClassDS = Seq(Person("Andy", 32)).toDS()
    caseClassDS.show()
    // +----+---+
    // |name|age|
    // +----+---+
    // |Andy| 32|
    // +----+---+     // 对于最常见的类型//编码器是通过导入spark.implicits._自动提供
    val primitiveDS = Seq(1, 2, 3).toDS()
    primitiveDS.map(_ + 1).collect() // Returns: Array(2, 3, 4)     //通过提供一个类可以将DataFrames转换为Dataset。映射将通过名称
    val path = "epeople.json"
    val peopleDS = spark.read.json(path).as[Person]
    peopleDS.show()
    // +----+-------+
    // | age|   name|
    // +----+-------+
    // |null|Michael|
    // |  30|   Andy|
    // |  19| Justin|
    // +----+-------+

7,与RDD进行互操作

       Spark SQL支持将现有RDD转换为Datasets的两种不同方法。第一种方法使用反射来推断包含特定类型对象的RDD的模式。这种基于反射的方法导致更简洁的代码,并且在编写Spark应用程序时已经知道模式的情况下工作良好。

创建数据集的第二种方法是通过编程接口,允许您构建模式,然后将其应用于现有的RDD。虽然这个方法比较冗长,但是它允许你在构造数据集的时候直到运行时才知道列和它们的类型。


// 用于从RDD到DataFrames的隐式转换
import spark.implicits._ // 从文本文件创建Person对象的RDD,将其转换为Dataframe 
val peopleDF = spark.sparkContext
.textFile("people.txt")
.map(_.split(","))
.map(attributes => Person(attributes(0), attributes(1).trim.toInt))
.toDF()
//将DataFrame注册为临时视图
peopleDF.createOrReplaceTempView("people") //SQL语句可以通过使用 Spark 提供的SQL方法运行
val teenagersDF = spark.sql("SELECT name, age FROM people WHERE age BETWEEN 13 AND 19") // 结果中的行的列可以通过字段索引
teenagersDF.map(teenager => "Name: " + teenager(0)).show()
// +------------+
// | value|
// +------------+
// |Name: Justin|
// +------------+ // 或通过字段名称
teenagersDF.map(teenager => "Name: " + teenager.getAs[String]("name")).show()
// +------------+
// | value|
// +------------+
// |Name: Justin|
// +------------+ // 没有为数据集[Map [K,V]]预定义的编码器,明确定义了
implicit val mapEncoder = org.apache.spark.sql.Encoders.kryo[Map[String, Any]]
// 原始类型和大小写类型也可以定义为
// implicit val stringIntMapEncoder: Encoder[Map[String, Any]] = ExpressionEncoder() //  row.getValuesMap [T]一栏立刻变成一个地图[String,T] 
teenagersDF.map(teenager => teenager.getValuesMap[Any](List("name", "age"))).collect()
// Array(Map("name" -> "Justin", "age" -> 19))

8,以编程方式指定模式

      当案例类不能提前定义时(例如,记录的结构是用字符串编码的,或者文本数据集将被解析,字段对不同的用户来说投影方式不同),DataFrame可以用三个步骤以编程方式创建一个。

          1,Row从原RDD 创建一个RDD;

          2, 创建在步骤1中创建的RDD中StructType与Rows 结构匹配 的模式。

          3,Row通过createDataFrame提供的方法将模式应用于s 的RDD SparkSession。

  import spark.implicits._
// 创建一个 RDD
val peopleRDD = spark.sparkContext.textFile("people.txt") // 模式用字符串编码
val schemaString = "name age" // 根据模式字符串
val fields = schemaString.split(" ")
.map(fieldName => StructField(fieldName, StringType, nullable = true))
val schema = StructType(fields) // 将RDD(人的记录)行
val rowRDD = peopleRDD
.map(_.split(","))
.map(attributes => Row(attributes(0), attributes(1).trim)) // 应用架构的RDD 
val peopleDF = spark.createDataFrame(rowRDD, schema) //使用DataFrame 
peopleDF.createOrReplaceTempView("people") // SQL可以在使用DataFrames 
val results = spark.sql("SELECT name FROM people") // SQL查询的结果是DataFrame并支持所有正常的RDD操作
// 结果中一行的列可以通过字段索引或字段名称
results.map(attributes => "Name: " + attributes(0)).show()
// +-------------+
// | value|
// +-------------+
// |Name: Michael|
// | Name: Andy|
// | Name: Justin|
// +-------------+

spark SQL (一)初识 ,简介的更多相关文章

  1. Spark SQL External DataSource简介

    随着Spark1.2的发布,Spark SQL开始正式支持外部数据源.这使得Spark SQL支持了更多的类型数据源,如json, parquet, avro, csv格式.只要我们愿意,我们可以开发 ...

  2. 【转载】Spark SQL之External DataSource外部数据源

    http://blog.csdn.net/oopsoom/article/details/42061077 一.Spark SQL External DataSource简介 随着Spark1.2的发 ...

  3. Spark SQL概念学习系列之Spark SQL的简介(一)

    Spark SQL提供在大数据上的SQL查询功能,类似于Shark在整个生态系统的角色,它们可以统称为SQL on Spark. 之前,Shark的查询编译和优化器依赖于Hive,使得Shark不得不 ...

  4. Spark SQL概念学习系列之SQL on Spark的简介(三)

    AMPLab 将大数据分析负载分为三大类型:批量数据处理.交互式查询.实时流处理.而其中很重要的一环便是交互式查询. 大数据分析栈中需要满足用户 ad-hoc.reporting. iterative ...

  5. 初识Spark2.0之Spark SQL

    内存计算平台spark在今年6月份的时候正式发布了spark2.0,相比上一版本的spark1.6版本,在内存优化,数据组织,流计算等方面都做出了较大的改变,同时更加注重基于DataFrame数据组织 ...

  6. Spark SQL Catalyst源代码分析之TreeNode Library

    /** Spark SQL源代码分析系列文章*/ 前几篇文章介绍了Spark SQL的Catalyst的核心执行流程.SqlParser,和Analyzer,本来打算直接写Optimizer的,可是发 ...

  7. Spark学习之Spark SQL

    一.简介 Spark SQL 提供了以下三大功能. (1) Spark SQL 可以从各种结构化数据源(例如 JSON.Hive.Parquet 等)中读取数据. (2) Spark SQL 不仅支持 ...

  8. Spark SQL在100TB上的自适应执行实践(转载)

    Spark SQL是Apache Spark最广泛使用的一个组件,它提供了非常友好的接口来分布式处理结构化数据,在很多应用领域都有成功的生产实践,但是在超大规模集群和数据集上,Spark SQL仍然遇 ...

  9. [Spark SQL_1] Spark SQL 配置

    0. 说明 Spark SQL 的配置基于 Spark 集群搭建  && Hive 的安装&配置 1. 简介 Spark SQL 是构建在 Spark Core 模块之上的四大 ...

随机推荐

  1. Servlet3.0提供的@WebServlet注解引用参数详情介绍

    Servlet3.0提供的@WebServlet注解: servlet3.0所提供的@webservlet注解,用来将某个类注解为一个servlet类,简化了web.xml上的servlet配置, @ ...

  2. 第14章节 BJROBOT karto 算法构建地图【ROS全开源阿克曼转向智能网联无人驾驶车】

    建地图前说明:请确保你的小车已经校正好 IMU.角速度.线速度,虚拟机配置好 ROS 网络的前提进行,否则会造成构建地图无边界.虚拟机端无法正常收到小车主控端发布的话题数据等异常情况!! 1.把小车平 ...

  3. 1. 内存分区模型以及new、delete操作

    C++程序在执行时,将内存大方向分为 4 个区域,不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程 代码区:存放函数二进制代码,由操作系统进行管理 全局区:存放全局变量和静态数据以及常量, ...

  4. Linux 下挂载新硬盘方法(转)

    1.关闭服务器加上新硬盘   2.启动服务器,以root用户登录   3.查看硬盘信息 #fdisk -l Disk /dev/sda: 42.9 GB, 42949672960 bytes 255  ...

  5. JavaScript高级程序设计(第4版)知识点总结

    介绍 JavaScript高级程序设计 第四版,在第三版的基础上添加了ES6相关的内容.如let.const关键字,Fetch API.工作者线程.模块.Promise 等.适合具有一定编程经验的 W ...

  6. C语言指针-从底层原理到花式技巧,用图文和代码帮你讲解透彻

    这是道哥的第014篇原创 目录 一.前言 二.变量与指针的本质 1. 内存地址 2. 32位与64位系统 3. 变量 4. 指针变量 5. 操作指针变量 5.1 指针变量自身的值 5.2 获取指针变量 ...

  7. LeetCode404.左叶子之和

    题目 法一.广度优先搜索 1 class Solution { 2 public: 3 int sumOfLeftLeaves(TreeNode* root) { 4 if(root == NULL) ...

  8. powershell中的cmdlet命令

    Add-Computer 向域或工作组中添加计算机. Add-Content 向指定的项中添加内容,如向文件中添加字词. Add-History 向会话历史记录追加条目. Add-Member 向 W ...

  9. [usaco2010 Oct]Soda Machine

    题目描述 有N个人要去膜拜JZ,他们不知道JZ会出现在哪里,因此每个人有一个活动范围,只要JZ出现在这个范围内就能被膜拜, 伟大的JZ当然希望膜拜他的人越多越好,但是JZ不能分身,因此只能选择一个位置 ...

  10. 导出exe的经验

    安装pyinstaller 首先要找到scripts的绝对路径(主要是找到scripts就行了 先是安装C:\Users\96290\AppData\Local\Programs\Python\Pyt ...