Spark 读写数据、抽象转换 拾遗
读
package com.test.spark
import org.apache.spark.sql.{Dataset, Row, SaveMode, SparkSession}
/**
* @author Administrator
* 2019/7/22-17:09
*
*/
object TestReadData {
val spark = SparkSession
.builder()
.appName("TestCreateDataset")
.config("spark.some.config.option", "some-value")
.master("local")
.enableHiveSupport()
.getOrCreate()
def main(args: Array[String]): Unit = {
testRead
}
def testRead(): Unit = {
// parquet 如果有损坏啥的容易莫名的错误
val parquet: Dataset[Row] = spark.read.parquet("D:\\DATA-LG\\PUBLIC\\TYGQ\\INF\\PersonInfoCommon.parquet")
parquet.show()
// Spark SQL 的通用输入模式
val commonRead: Dataset[Row] = spark.read.format("json").load("D:\\DATA-LG\\PUBLIC\\TYGQ\\INF\\testJson")
commonRead.show()
// Spark SQL 的通用输出模式
commonRead.write.format("parquet").mode(SaveMode.Append).save("D:\\DATA-LG\\PUBLIC\\TYGQ\\INF\\PersonInfoCommon.parquet")
// Spark SQL 的专业输入模式
val professionalRead: Dataset[Row] = spark.read.json("D:\\DATA-LG\\PUBLIC\\TYGQ\\INF\\testJson")
professionalRead.show()
// Spark SQL 的专业输出模式
professionalRead.write.mode(SaveMode.Append).parquet("D:\\DATA-LG\\PUBLIC\\TYGQ\\INF\\PersonInfoProfessional.parquet")
val readParquet: Dataset[Row] = spark.sql("select * from parquet.`D:\\DATA-LG\\PUBLIC\\TYGQ\\INF\\PersonInfoCommon.parquet`")
readParquet.show()
}
}
//输出:
+---+---------------+---------+
|age| ip| name|
+---+---------------+---------+
| 24| 192.168.0.8| lillcol|
|100| 192.168.255.1| adson|
| 39| 192.143.255.1| wuli|
| 20| 192.168.255.1| gu|
| 15| 243.168.255.9| ason|
| 1| 108.168.255.1| tianba|
| 25|222.168.255.110|clearlove|
| 30|222.168.255.110|clearlove|
+---+---------------+---------+
+---+---------------+---------+
|age| ip| name|
+---+---------------+---------+
| 24| 192.168.0.8| lillcol|
|100| 192.168.255.1| adson|
| 39| 192.143.255.1| wuli|
| 20| 192.168.255.1| gu|
| 15| 243.168.255.9| ason|
| 1| 108.168.255.1| tianba|
| 25|222.168.255.110|clearlove|
| 30|222.168.255.110|clearlove|
+---+---------------+---------+
+---+---------------+---------+
|age| ip| name|
+---+---------------+---------+
| 24| 192.168.0.8| lillcol|
|100| 192.168.255.1| adson|
| 39| 192.143.255.1| wuli|
| 20| 192.168.255.1| gu|
| 15| 243.168.255.9| ason|
| 1| 108.168.255.1| tianba|
| 25|222.168.255.110|clearlove|
| 30|222.168.255.110|clearlove|
+---+---------------+---------+
+---+---------------+---------+
|age| ip| name|
+---+---------------+---------+
| 24| 192.168.0.8| lillcol|
|100| 192.168.255.1| adson|
| 39| 192.143.255.1| wuli|
| 20| 192.168.255.1| gu|
| 15| 243.168.255.9| ason|
| 1| 108.168.255.1| tianba|
| 25|222.168.255.110|clearlove|
| 30|222.168.255.110|clearlove|
| 24| 192.168.0.8| lillcol|
|100| 192.168.255.1| adson|
| 39| 192.143.255.1| wuli|
| 20| 192.168.255.1| gu|
| 15| 243.168.255.9| ason|
| 1| 108.168.255.1| tianba|
| 25|222.168.255.110|clearlove|
| 30|222.168.255.110|clearlove|
+---+---------------+---------+
保存
文件保存选项
模式 | 注释 |
---|---|
Append | DataFrame的内容将被追加到现有数据中。 |
Overwrite | 现有数据将被数据Daframe的内容覆盖。 |
ErrorIfExists | 如果数据已经存在,报错。 |
Ignore | 如果数据已经存在,不执行任何操作 |
注:这些保存模式不使用任何锁定,不是原子操作。
如果使用 Overwrite 同时该路径(path)又是数据源路径,要先对数据进行持久化操作,
否则会在读取path之前将该数据删除掉,导致后续lazy 读取数据的时候报文件不存在的错误。
类型之间的转换
之前关于Spark 三中抽象之间的转换老是有些纠结
现在对它们之间的转换做个总结
在 SparkSQL 中 Spark 为我们提供了两个新的抽象,分别是 DataFrame 和 DataSet。
他们和 RDD 有什啥关系呢?
首先从版本的产生上来看:RDD(Spark1.0) —> DataFrame(Spark1.3) —> DataSet(Spark1.6)
如果同样的数据都给到这三个数据结构,他们分别计算之后,都会给出相同的结果。
不同是的他们的执行效率和执行方式。
在后期的 Spark 版本中,DataSet 会逐步取代 RDD 和 DataFrame 成为唯一的 API 接口。
所以后续开发 我更多的面向DataSet进行开发了。
RDD
- RDD 弹性分布式数据集,Spark 计算的基石,为用户屏蔽了底层对数据的复杂抽象和处理,为用户提供了一组方便的数据转换与求值方法。
- RDD 是一个懒执行的不可变的可以支持 Lambda 表达式的并行数据集合。
- RDD 的最大好处就是简单,API 的人性化程度很高。
- RDD 的劣势是性能限制,它是一个 JVM 驻内存对象,这也就决定了存在 GC 的限制和数据增加时 Java 序列化成本的升高。
DataFrame
- 与 RDD 类似,DataFrame 也是一个分布式数据容器。
- 然而 DataFrame 更像传统数据库的二维表格,除了数据以外,还记录数据的结构信息,即 schema。
- 与 Hive 类似,DataFrame 也支持嵌套数据类型(struct、array 和 map)。
- 从 API 易用性的角度上看,DataFrame API 提供的是一套高层的关系操作,比函数式的 RDD API 要更加友好,门槛更低。
- 由于与 R 和 Pandas 的 DataFrame 类似,Spark DataFrame 很好地继承了传统单机数据分析的开发体验。
Q: DataFrame性能上比 RDD 要高的原因:
A:主要有两个原因
- 定制化内存管理
数据以二进制的方式存在于非堆内存,节省了大量空间之外,还摆脱了 GC 的限制。
- 优化的执行计划
查询计划通过 Spark catalyst optimiser 进行优化。
DataSet
- 是 DataFrame API 的一个扩展,是 Spark 最新的数据抽象。
- 用户友好的 API 风格,既具有类型安全检查也具有 DataFrame 的查询优化特性。
- DataSet 支持编解码器,当需要访问非堆上的数据时可以避免反序列化整个对象,提高了效率。
- 样例类被用来在 DataSet 中定义数据的结构信息,样例类中每个属性的名称直接映射到 DataSet 中的字段名称。
- DataFrame 是 DataSet 的特列,type DataFrame = Dataset[Row] ,所以可以通过 as 方法将 DataFrame 转换为 DataSet。Row 是一个类型,跟 Car、Person 这些的类型一样,所有的表结构信息都用 Row 来表示。
- DataSet 是强类型的。比如可以有 Dataset[Car],Dataset[Person],
DataFrame 只是知道字段,但是不知道字段的类型,所以在执行这些操作的时候是没办法在编译的时候检查是否类型失败的,比如你可以对一个 String 进行减法操作,在执行的时候才报错,
而 DataSet 不仅仅知道字段,而且知道字段类型,所以有更严格的错误检查。
就跟 JSON 对象和类对象之间的类比。
三者之间的转换
case class Person(name: String, age: Long) extends Serializable //case class的定义要在引用case class函数的外面。
import spark.implicits._
//类型之间的转换:注意输出类型
def rddSetFrame() = {
// 在使用一些特殊的操作时,一定要加上 import spark.implicits._ 不然 toDF、toDS 无法使用。
val rdd: RDD[String] = spark.sparkContext.textFile("D:\\DATA-LG\\PUBLIC\\TYGQ\\INF\\testFile")
val ds: Dataset[Row] = spark.read.json("D:\\DATA-LG\\PUBLIC\\TYGQ\\INF\\testJson")
val df: DataFrame = rdd.map(_.split(",")).map(strArr => (strArr(0).trim(), strArr(1).trim().toInt)).toDF("nama", "age")
// rdd->df
//一般用元组把一行的数据写在一起,然后在 toDF 中指定字段名。
val rddTDf: DataFrame = rdd.map(_.split(",")).map(strArr => (strArr(0).trim(), strArr(1).trim().toInt)).toDF("nama", "age")
// df -> rdd
val dfTRdd: RDD[Row] = df.rdd;
// rdd -> ds
//定义每一行的类型 case class 时,已经给出了字段名和类型,后面只要往 case class 里面添加值即可。
val rddTDs: Dataset[Person] = rdd.map(_.split(",")).map(strArr => Person(strArr(0).trim(), strArr(1).trim().toInt)).toDS()
// ds -> rdd
val dsTRdd: RDD[Person] = rddTDs.rdd
// df->ds
//这种方法就是在给出每一列的类型后,使用 as 方法,转成 DataSet,这在数据类型是 DataFrame 又需要针对各个字段处理时极为方便。
val dfTDs: Dataset[Person] = df.as[Person]
// ds->df
// 只是把 case class 封装成 Row。
val dsTDf: DataFrame = ds.toDF
}
Spark 读写数据、抽象转换 拾遗的更多相关文章
- Spark SQL数据加载和保存实战
一:前置知识详解: Spark SQL重要是操作DataFrame,DataFrame本身提供了save和load的操作, Load:可以创建DataFrame, Save:把DataFrame中的数 ...
- Spark大数据针对性问题。
1.海量日志数据,提取出某日访问百度次数最多的那个IP. 解决方案:首先是将这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中.注意到IP是32位的,最多有个2^32个IP.同样可以采 ...
- 使用Spark读写CSV格式文件(转)
原文链接:使用Spark读写CSV格式文件 CSV格式的文件也称为逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号.在本文中的CSV格 ...
- Spark SQL数据载入和保存实战
一:前置知识具体解释: Spark SQL重要是操作DataFrame,DataFrame本身提供了save和load的操作. Load:能够创建DataFrame. Save:把DataFrame中 ...
- Spark 读写hive 表
spark 读写hive表主要是通过sparkssSession 读表的时候,很简单,直接像写sql一样sparkSession.sql("select * from xx") 就 ...
- Spark读写HBase
Spark读写HBase示例 1.HBase shell查看表结构 hbase(main)::> desc 'SDAS_Person' Table SDAS_Person is ENABLED ...
- 学习Hadoop+Spark大数据巨量分析与机器学习整合开发-windows利用虚拟机实现模拟多节点集群构建
记录学习<Hadoop+Spark大数据巨量分析与机器学习整合开发>这本书. 第五章 Hadoop Multi Node Cluster windows利用虚拟机实现模拟多节点集群构建 5 ...
- opencv IplImage各参数详细介绍以及如何从一个JPEG图像数据指针转换得到IplImage
这篇文章里介绍得最清楚了.http://blog.chinaunix.net/uid-22682903-id-1771421.html 关于颜色空间 RGB颜色空间已经非常熟悉了.HSV颜色空间需要 ...
- Python 学习 第17篇:从SQL Server数据库读写数据
在Python语言中,从SQL Server数据库读写数据,通常情况下,都是使用sqlalchemy 包和 pymssql 包的组合,这是因为大多数数据处理程序都需要用到DataFrame对象,它内置 ...
随机推荐
- 关于mybaitis
mybatis启动流程 1.首先来看看最简单的mybatis项目启动过程 public static void mybatisTest() throws IOException { String re ...
- HTML——表单标签
表单标签(掌握) 现实中的表单,类似我们去银行办理信用卡填写的单子. 如下图: 目的是为了收集用户信息. 在我们网页中, 我们也需要跟用户进行交互,收集用户资料,此时也需要表单. 在HTML中,一个完 ...
- NOI2019赛前两周被吊打记录
7.1 T1看了半天发现会个暴力FWT,然后突然返发现随便容斥一下就好了 T2猜了个只有13和23的,结果打个表发现伪了,然后标号不只一种连搜索都写错了,也没想过可以轮廓线dp,菜哭了o(╥﹏╥)o ...
- ETL详解
ETL是将业务系统的数据经过抽取.清洗转换之后加载到数据仓库的过程,目的是将企业中的分散.零乱.标准不统一的数据整合到一起,为企业的决策提供分析依据. ETL是BI项目重要的一个环节. 通常情况下,在 ...
- USACO 06JAN 牛的舞会 洛谷2863
题目描述 The N (2 <= N <= 10,000) cows are so excited: it's prom night! They are dressed in their ...
- IP总结
网络层向上只提供无连接的.尽最大努力支付的数据报服务 IP地址,32位,分为两部分,网络和主机标示 IP地址分类: A类:0开头,1-8位为网络标示 B类:10开头,1-16位为网络标示 C类:110 ...
- 基于Netty的RPC架构学习笔记(三):netty客户端
文章目录 举个
- 实战CGLib系列之proxy篇(一):方法拦截MethodInterceptor
实战CGLib系列文章 本篇介绍通过MethodInterceptor和Enhancer实现一个动态代理. 一.首先说一下JDK中的动态代理: JDK中的动态代理是通过反射类Proxy以及Invoca ...
- SPI 通信
Frm: http://www.wzaobao.com/p/l5079K.html http://blog.csdn.net/xqmoo8/article/details/8043474 http:/ ...
- SVG动画制作工具 , 从此抛弃臃肿的gif
VG简介 只要是程序员的你,你不得不知道svg图片,它可以无限任意放大拉伸都不会损失画质,就像系统字体一样可以无限矢量放大,svg更高级是可以用来制作矢量动画,现在各大浏览器和系统基本对svg已经支持 ...