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
  1. RDD 弹性分布式数据集,Spark 计算的基石,为用户屏蔽了底层对数据的复杂抽象和处理,为用户提供了一组方便的数据转换与求值方法。
  2. RDD 是一个懒执行的不可变的可以支持 Lambda 表达式的并行数据集合。
  3. RDD 的最大好处就是简单,API 的人性化程度很高。
  4. RDD 的劣势是性能限制,它是一个 JVM 驻内存对象,这也就决定了存在 GC 的限制和数据增加时 Java 序列化成本的升高。
DataFrame
  1. 与 RDD 类似,DataFrame 也是一个分布式数据容器。
  2. 然而 DataFrame 更像传统数据库的二维表格,除了数据以外,还记录数据的结构信息,即 schema。
  3. 与 Hive 类似,DataFrame 也支持嵌套数据类型(struct、array 和 map)。
  4. 从 API 易用性的角度上看,DataFrame API 提供的是一套高层的关系操作,比函数式的 RDD API 要更加友好,门槛更低。
  5. 由于与 R 和 Pandas 的 DataFrame 类似,Spark DataFrame 很好地继承了传统单机数据分析的开发体验。

Q: DataFrame性能上比 RDD 要高的原因:

A:主要有两个原因

  1. 定制化内存管理
    数据以二进制的方式存在于非堆内存,节省了大量空间之外,还摆脱了 GC 的限制。
  2. 优化的执行计划
    查询计划通过 Spark catalyst optimiser 进行优化。
DataSet
  1. 是 DataFrame API 的一个扩展,是 Spark 最新的数据抽象。
  2. 用户友好的 API 风格,既具有类型安全检查也具有 DataFrame 的查询优化特性。
  3. DataSet 支持编解码器,当需要访问非堆上的数据时可以避免反序列化整个对象,提高了效率。
  4. 样例类被用来在 DataSet 中定义数据的结构信息,样例类中每个属性的名称直接映射到 DataSet 中的字段名称。
  5. DataFrame 是 DataSet 的特列,type DataFrame = Dataset[Row] ,所以可以通过 as 方法将 DataFrame 转换为 DataSet。Row 是一个类型,跟 Car、Person 这些的类型一样,所有的表结构信息都用 Row 来表示。
  6. 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 }

最新文章

  1. Xamarin.ios 重新定位视图
  2. C#基础知识记录一
  3. 删除ORACLE的步骤
  4. 在脚本中使用export导出变量值
  5. 关于GreenOdoo的一个Bug
  6. python 字符编码问题
  7. 调皮的转义之addslashes
  8. 【转载】gcc和g++的区别
  9. Python学习的一些好资料
  10. 对List
  11. HDU 3065 病毒在继续 (AC自己主动机)
  12. Message Queuing(MSMQ)
  13. css处理事件透过、点击事件透过
  14. mysql更新表中日期字段时间
  15. DDD领域模型查询方法实现(八)
  16. Invoke和BeginInvoke理解
  17. extends 扩展选项
  18. 整理:FPGA选型
  19. object-c输出对象
  20. Log4Net各参数API

热门文章

  1. 使用Git 上传文件到云端(版本库)
  2. twentytwenty插件,图片对比轮播
  3. [原创]Delphi 字符串函数(字符串判断 TryStrToFloat 、TryStrToInt、TryStrToInt64、TryStrToBool、TryStrToCurr、TryStrToDate、TryStrToTime、TryStrToDateTime)
  4. Openssl命令的使用
  5. 40 VSCode下.json文件的编写——(1) linux/g++ (2).json中参数与预定义变量的意义解释
  6. 检测API函数的InlineHook
  7. (转)在Source Insight中看Python代码
  8. python array基本操作一
  9. luogu3384 /// 树链剖分+线段树模板
  10. vue点击跳转拨号界面