文档章节

spark2.2官方教程笔记-Spark SQL, DataFrames and Datasets向导

skanda
 skanda
发布于 2017/08/07 17:17
字数 1812
阅读 876
收藏 2

概括

spark SQL是一个spark结构数据处理模型。不像基本的rdd api,Spark 提供的接口可以给spark提供更多更多关于数据的结构和正在执行的计算的信息。另外,spark sql在性能优化上比以往的有做改善。目前有更多的方式和spark sql交互:sql,dataset api。无论你是用哪种api/语言,计算时最终使用相同的sql引擎。

SQL

  Spark Sql的一个作用是执行sql查询。spark sql能够用来从现有的hive中读取数据。更多关于如何配置使用的问题,请参考Hibe 表章节。当使用其他编程语言运行sql,结果也将返回Dataset/DataFrame。你能通过使用命令行或者jdbc/odbc和sql接口交互。

Datasets and DataFrames

一个dataset是分布式数据集合。数据集合是一个spark1.6开始提供的接口,想要把rdd的优势(强类似,强大的lambda函数功能)和spark sql的优化执行的优势结合到一起来。dataset能够从jvm对象中创建然后使用transformations(map,flagmap,filter等等)进行转换。

开始

SparkSession

所有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()

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

更完整的代码可以在spark安装包

examples/src/main/scala/org/apache/spark/examples/sql/SparkSQLExample.scala

路径下查看。

在spark2.0中SparkSession提供了内部对Hive功能的支持,包括查询HiveSql,访问Hive UDFs,以及从Hive表读数据的能力。要使用这些特征,你不需要单独安装一个hive。

创建DataFrames

通过SparkSession,应用能够由现有的rdd,或者hive表,或者spark数据源创建DataFrames。举个栗子,通过json文件创建

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

// Displays the content of the DataFrame to stdout
df.show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

非强类型/泛型 数据集操作(又叫做DataFrame操作)

DataFrames提供一个专用的语言来操作结构化数据。

如上所述,在Spark2.0中,DataFrames只是包含Rows的数据集。相对“强类型转换”这些被称作弱类型转换。【烂英文有时候翻译起来自己都不知道官方文档想表达啥。】

还是下面的代码好理解

// This import is needed to use the $-notation
import spark.implicits._
// Print the schema in a tree format
df.printSchema()
// root
// |-- age: long (nullable = true)
// |-- name: string (nullable = true)

// Select only the "name" column
df.select("name").show()
// +-------+
// |   name|
// +-------+
// |Michael|
// |   Andy|
// | Justin|
// +-------+

// Select everybody, but increment the age by 1
df.select($"name", $"age" + 1).show()
// +-------+---------+
// |   name|(age + 1)|
// +-------+---------+
// |Michael|     null|
// |   Andy|       31|
// | Justin|       20|
// +-------+---------+

// Select people older than 21
df.filter($"age" > 21).show()
// +---+----+
// |age|name|
// +---+----+
// | 30|Andy|
// +---+----+

// Count people by age
df.groupBy("age").count().show()
// +----+-----+
// | age|count|
// +----+-----+
// |  19|    1|
// |null|    1|
// |  30|    1|
// +----+-----+

更全的操作请移步api文档

除了简单的列引用和表达式,datasets也有丰富的函数库包括字符串操作,时间计算,常用的数学操作等。具体请移步DataFrame Function Reference.

执行Sql查询

SparkSession sql功能使应用可以执行一串sql查询并且返回一个DataFrame。把sql引入了语言。

// Register the DataFrame as a SQL temporary view
df.createOrReplaceTempView("people")

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

全局临时视图

临时视图的生命周期在Session范围内,随着session的停止而释放。如果你要让所有的session的可以访问,那么你就要搞个全局临时视图了。这个视图绑定在系统保留的global_temp数据库中,访问前我们必须通过引用gloabal_temp来访问它。 e.g. SELECT * FROM global_temp.view1.

// Register the DataFrame as a global temporary view
df.createGlobalTempView("people")

// Global temporary view is tied to a system preserved database `global_temp`
spark.sql("SELECT * FROM global_temp.people").show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

// Global temporary view is cross-session
spark.newSession().sql("SELECT * FROM global_temp.people").show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

创建Datasets

 datasets和rdds类似,和java序列化相反的是,他们使用特殊的编码方式去序列化对象。

// Note: Case classes in Scala 2.10 can support only up to 22 fields. To work around this limit,
// you can use custom classes that implement the Product interface
case class Person(name: String, age: Long)

// Encoders are created for case classes
val caseClassDS = Seq(Person("Andy", 32)).toDS()
caseClassDS.show()
// +----+---+
// |name|age|
// +----+---+
// |Andy| 32|
// +----+---+

// Encoders for most common types are automatically provided by importing spark.implicits._
val primitiveDS = Seq(1, 2, 3).toDS()
primitiveDS.map(_ + 1).collect() // Returns: Array(2, 3, 4)

// DataFrames can be converted to a Dataset by providing a class. Mapping will be done by name
val path = "examples/src/main/resources/people.json"
val peopleDS = spark.read.json(path).as[Person]
peopleDS.show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

和rdd对象交互

两种从rdd对象转换到dataset的方法。第一种是使用反射来反推一个rdd的对象类型。第二种是通过一个现有的rdd和你构建的schema,并且这种方式允许创建泛型,到运行时再来定义。

反射推理schema

先建好schema对应的类型,在map过程加进去。show code

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

// Create an RDD of Person objects from a text file, convert it to a Dataframe
val peopleDF = spark.sparkContext
  .textFile("examples/src/main/resources/people.txt")
  .map(_.split(","))
  .map(attributes => Person(attributes(0), attributes(1).trim.toInt))
  .toDF()
// Register the DataFrame as a temporary view
peopleDF.createOrReplaceTempView("people")

// SQL statements can be run by using the sql methods provided by Spark
val teenagersDF = spark.sql("SELECT name, age FROM people WHERE age BETWEEN 13 AND 19")

// The columns of a row in the result can be accessed by field index
teenagersDF.map(teenager => "Name: " + teenager(0)).show()
// +------------+
// |       value|
// +------------+
// |Name: Justin|
// +------------+

// or by field name
teenagersDF.map(teenager => "Name: " + teenager.getAs[String]("name")).show()
// +------------+
// |       value|
// +------------+
// |Name: Justin|
// +------------+

// No pre-defined encoders for Dataset[Map[K,V]], define explicitly
implicit val mapEncoder = org.apache.spark.sql.Encoders.kryo[Map[String, Any]]
// Primitive types and case classes can be also defined as
// implicit val stringIntMapEncoder: Encoder[Map[String, Any]] = ExpressionEncoder()

// row.getValuesMap[T] retrieves multiple columns at once into a Map[String, T]
teenagersDF.map(teenager => teenager.getValuesMap[Any](List("name", "age"))).collect()
// Array(Map("name" -> "Justin", "age" -> 19))

编程式定义schema

import org.apache.spark.sql.types._

// Create an RDD
val peopleRDD = spark.sparkContext.textFile("examples/src/main/resources/people.txt")

// The schema is encoded in a string
val schemaString = "name age"

// Generate the schema based on the string of schema
val fields = schemaString.split(" ")
  .map(fieldName => StructField(fieldName, StringType, nullable = true))
val schema = StructType(fields)

// Convert records of the RDD (people) to Rows
val rowRDD = peopleRDD
  .map(_.split(","))
  .map(attributes => Row(attributes(0), attributes(1).trim))

// Apply the schema to the RDD
val peopleDF = spark.createDataFrame(rowRDD, schema)

// Creates a temporary view using the DataFrame
peopleDF.createOrReplaceTempView("people")

// SQL can be run over a temporary view created using DataFrames
val results = spark.sql("SELECT name FROM people")

// The results of SQL queries are DataFrames and support all the normal RDD operations
// The columns of a row in the result can be accessed by field index or by field name
results.map(attributes => "Name: " + attributes(0)).show()
// +-------------+
// |        value|
// +-------------+
// |Name: Michael|
// |   Name: Andy|
// | Name: Justin|
// +-------------+

聚合

内建的dataframe函数提供常用的聚合函数,比如count,countDistinct,avg,max,min等等。

 

一个本地测试例子:

启动shell,加入mysql驱动包
spark-shell --master spark://hadoop-master:7077 --jars /root/mysql-connector-java-5.1.47.jar
从hdfs取文本文件
val userTxt = sc.textFile("hdfs://hadoop-master:9000//12306.txt");
import org.apache.spark.sql.Row
根据----分割数据
val userRdd = userTxt.map(_.split("----")).map(parts=>Row(parts(0),parts(1),parts(2),parts(3),parts(4),parts(5),parts(6)))
表元数据准备
val schemaString="email,acount,username,sfz,password,mobile,email1"
import org.apache.spark.sql.types._
val fields = schemaString.split(",").map(fieldName => StructField(fieldName, StringType, nullable = true))
val schema =StructType(fields)
rdd数据转df数据
val userDf = spark.createDataFrame(userRdd, schema)
数据写入mysql数据库
userDf.write.format("jdbc").option("url", "jdbc:mysql://192.168.199.204:3306/aaa").option("dbtable", "aaa").option("SaveMode","Overwrite").option("user", "root").option("password", "root").option("driver","com.mysql.jdbc.Driver").save()
  

 

© 著作权归作者所有

skanda
粉丝 11
博文 107
码字总数 60585
作品 0
厦门
私信 提问
加载中

评论(0)

Spark 官方博文专区(目录)

关于转载一些 Spark 官方的文档以及 DataBricks 公司博文,本系列基本是中英双语,主要是为了提高自己的英语水平。 文章分类 spark databricks A Tale of Three Apache Spark APIs: RDDs, Da...

虾皮
2018/04/03
0
0
Introducing Apache Spark Datasets(中英双语)

文章标题 Introducing Apache Spark Datasets 作者介绍 Michael Armbrust, Wenchen Fan, Reynold Xin and Matei Zaharia 文章正文 Developers have always loved Apache Spark for providin......

虾皮
2018/04/04
0
0
[电子书]Spark: The Definitive Guide Early Release PDF下载

阿里云智能数据库事业部 OLAP 平台团队现向 2021 届海内外院校应届毕业生(毕业时间在2020年11月-2021年10月之间)招聘大数据系统工程师,有机会转正,有意请加 iteblog 微信内推。 本书作者...

Spark
2017/06/22
0
0
A Tale of Three Apache Spark APIs: RDDs, DataFrames, and Datasets(中英双语)

文章标题 A Tale of Three Apache Spark APIs: RDDs, DataFrames, and Datasets 且谈Apache Spark的API三剑客:RDD、DataFrame和Dataset When to use them and why 什么时候用他们,为什么?......

osc_r0xr7i5d
2018/04/03
4
0
你不能错过的 spark 学习资源

1. 书籍,在线文档 2. 网站 3. Databricks Blog 4. 文章,博客 5. 视频

u012608836
2018/04/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

web测试与app测试的区别

web测试与app测试的区别 首先从系统架构来看的话: web项目,一般都是b/s架构,基于浏览器的,而app则是c/s的,必须要有客户端。那么在系统测试测试的时候就会产生区别了。 web测试只要更新了...

osc_qo89by3k
25分钟前
16
0
【mysql 读写分离】10分钟了解读写分离的作用

1、什么是读写分离 读写分离,基本的原理是让主数据库处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集...

战略板儿砖
26分钟前
27
0
Sphinx和rst在科研笔记和学术博客中的高效用法

什么是RST? reStructuredText 是扩展名为 .rst 的纯文本文件,含义为"重新构建的文本",也被简称为:RST 或 reST; 是 Python 编程语言的 Docutils 项目的一部分,Python Doc-SIG (Documen...

osc_6b3uvobr
27分钟前
17
0
MySQL 的 crash-safe 原理解析

本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/5i9wmJs4_Er7RaYfNnETyA 作者:xieweipeng MySQL作为当下最流行的开源关系型数据库,有一个很关键和基本的能力,就...

vivo互联网技术
27分钟前
23
0
Org Mode - 年轻人的第一堂时间管理课程

忙成狗,闲成猪。 上半年我的状态就是如此,为了做出改变我找了很多的任务管理工具,比如奇妙清单、滴答清单(现在我还在用)等等,但是依然没有满足我的需求。作为一名精力旺盛的开发仔,我...

osc_smzoc82r
28分钟前
19
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部