Spark之 RDD、DataSet、DataFrame

本文深入探讨了Spark生态中的关键组件,包括SparkContext、SparkSession、StreamingContext的作用及相互关系,详细对比了RDD、DataFrame与DataSet的数据抽象特性,以及它们在序列化、内存管理和性能上的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言 

  1. SparkContext是RDD的环境
  2. SparkSession是DataSet和DataFrame的环境,SparkSession内部封装了SparkContext
  3. StreamingContext是Spark streaming得环境,底层封装了SparkContext
// 创建RDD 得 SparkContext 环境
val sparkConf: SparkConf = new SparkConf().setAppName("haha").setMaster("local[*]")
val sc = new SparkContext(sparkConf)

// 创建 spark sql 环境
val spark: SparkSession = SparkSession.builder().master("local[*]").appName("haha").getOrCreate()

// 创建 Spark streaming 环境
val sparkConf: SparkConf = new SparkConf().setAppName("haha").setMaster("local[*]")

val ssc = new StreamingContext(sparkConf,Seconds(3))
  • SparkSql是将SparkSql转换成RDD然后再执行
  • SparkSql提供了两个数据抽象:DataSet和DataFrame

共性

RDD

  • 使用java序列化,序列化结果比较大,而且数据存储在java对内存中,导致gc比较频繁
  • RDD[Person],以person为类型参数,但Spark本身不了解Person的内部结构
  • 类型安全,写代码时就可以看出是否出错
val spark: SparkSession = SparkSession.builder().master("local[*]").appName("haha").getOrCreate()
        import spark.implicits._
        val ssc: SparkContext = spark.sparkContext

        val rdd: RDD[(String, Int)] = ssc.makeRDD(Array(("a", 1), ("b", 2)))

        rdd.foreach(line => {
            println(line._1 + "_" +line._2)
        })

 DataFrame

  • 采用kryo序列化,由于数据辕信息spark已经保存,序列化时不需要带上元信息,序列化的只有数据本身。且数据保存在堆外内存中,较少了gc次数,所以运行更快
  • DataFrame提供了详细的结构信息,类似于数据库中的一张表,性能比RDD快,因为经过优化
  • 类型不安全
df.foreach{
            line=>
                // DataFrame每一行的类型固定为Row,只有通过解析才能获取各个字段的值
                val col1: Unit = line.getAs[String]("col1")
                val col2: String = line.getAs[String]("col2")
                // 第二种方法
                val col1 : String = line.getString(1)
        }

 DataSet

  • DataSet(1.6才有),和DataFrame一样,使用kryo序列化,采用堆外内存
  • 类型安全
  1. 样例类被用来在DataSet中定义数据的结构信息,样例类中的每个属性的名称直接映射到DataSet中的字段名称
  2. DaraFrame是DataSet的特例,DataFrame = DataSet[Row],Row是一个类型,可以是Car、Person,或者说样例类。
  3. DataFrame只知道字段,不知道字段的类型,所以没办法再编译的时候检查是否类型失败的。而DataSet不仅知道字段,还知道类型
object test11 {
    def main(args: Array[String]): Unit = {

        val spark: SparkSession = SparkSession.builder().master("local[*]").appName("haha").getOrCreate()
        import spark.implicits._
        val ssc: SparkContext = spark.sparkContext

        val rdd: RDD[(String, Int)] = ssc.makeRDD(Array(("a", 1), ("b", 2), ("c", 3)))
        
        val ds: Dataset[Coltest] = rdd.map(line =>
            Coltest(line._1, line._2)
        ).toDS()

        ds.map {
            line =>
                // 可以直接访问 DS 中的字段
                println(line.col1)
                println(line.col2)
        }
        
    }
}

case class Coltest(col1: String, col2: Int) extends Serializable //定义字段名和类型

 

<think>好的,我现在需要帮助用户理解Spark中的RDDDataFrameDataSet的区别与用法。首先,我得回顾一下自己对这些概念的理解,确保没有错误。根据用户提供的引用资料,我需要整理出它们的主要特点和不同之处。 首先,RDDSpark最早的数据结构,弹性分布式数据集,提供低层次的API,处理非结构化数据时比较灵活,但可能效率不高。用户给的引用提到RDD不支持Spark SQL操作,而且Spark不了解其内部结构,比如RDD[Person]中的Person类结构对Spark来说是透明的,这样优化可能受限。 接下来是DataFrame,它是在Spark 1.3引入的,以列的形式组织数据,类似于关系型数据库的表,有schema信息。这样Spark SQL可以利用结构信息进行优化,比如过滤、聚合等操作会更高效。引用1和3提到DataFrame是分布式的Row对象,有明确的列名和类型,支持SQL查询,适合结构化数据处理。但DataFrame的缺点可能是类型安全不够,因为Row是泛型,编译时无法检查类型错误。 然后是DataSetSpark 1.6引入,结合了RDDDataFrame的优点,提供强类型支持,同时利用优化器进行性能优化。引用1指出DataSet每个记录存储的是强类型值,而不是Row,这样可以在编译时捕捉错误,适合需要类型安全的场景。引用4提到版本演进,从RDDDataFrame再到DataSet,说明DataSet是更高级的抽象。 接下来需要比较三者的区别和适用场景。比如,RDD适合需要细粒度控制的场景,比如非结构化数据或复杂的数据处理逻辑;DataFrame适合结构化数据,需要SQL操作或优化执行计划的情况;DataSet则结合两者,适合需要类型安全和高效计算的场景,特别是使用Scala的情况。 用户可能还想知道如何选择这三者,或者它们之间的性能差异。比如,DataFrameDataSet因为有Catalyst优化器和Tungsten执行引擎,通常比RDD更快。此外,类型安全也是一个考虑因素,DataSet在Scala中可以提供编译时检查,而Python可能不支持DataSet。 需要确保回答结构清晰,分点说明每个概念的特点、区别、使用场景,并引用提供的资料来支持观点。同时,生成相关问题时要围绕这三个数据结构的应用和比较,比如优化方法、性能对比等。 最后,检查是否符合用户的要求,比如使用中文,LaTeX格式正确,添加引用标识,生成相关问题等。确保没有遗漏任何引用内容,并且正确对应引用编号。</think>### SparkRDDDataFrameDataSet的区别与用法 #### 1. **RDD(弹性分布式数据集)** - **核心特点**: - **低层次API**:RDDSpark最基础的抽象,提供细粒度的控制(如分区、容错等)[^4]。 - **无结构数据**:数据以分布式Java对象形式存储,Spark不了解其内部结构[^1]。 - **灵活性**:支持复杂的非结构化数据处理(如文本、图像)[^2]。 - **代码示例**: ```scala val rdd = sc.textFile("data.txt").flatMap(_.split(" ")) ``` - **缺点**:缺乏执行优化(如Catalyst优化器),不支持SQL操作[^1][^3]。 --- #### 2. **DataFrame** - **核心特点**: - **结构化数据**:以列形式组织数据,包含明确的Schema(列名、类型)[^1]。 - **高性能优化**:通过Catalyst优化器生成高效执行计划,支持Tungsten二进制存储。 - **SQL兼容**:可直接用Spark SQL查询,适合ETL、聚合分析等场景[^2]。 - **代码示例**: ```python df = spark.read.json("data.json") df.filter(df["age"] > 20).show() ``` - **缺点**:编译时无类型检查(如Python中列名错误需运行时发现)[^1]。 --- #### 3. **DataSet** - **核心特点**: - **强类型支持**:结合RDD的类型安全和DataFrame的优化(主要适用于Scala/Java)。 - **混合优势**:支持函数式编程(如`map`、`filter`),同时享受Catalyst优化[^4]。 - **统一接口**:在Spark 2.0后,DataFrame成为`DataSet[Row]`的别名。 - **代码示例**: ```scala case class Person(name: String, age: Int) val ds = spark.read.json("data.json").as[Person] ``` - **缺点**:对Python支持有限(Python无强类型特性)[^1]。 --- ### § 三者的区别总结 | **特性** | **RDD** | **DataFrame** | **DataSet** | |-------------------|-----------------------|-----------------------|-----------------------| | **数据形式** | 分布式对象集合 | 结构化表格(Row对象) | 强类型对象集合 | | **优化能力** | 无 | Catalyst + Tungsten | Catalyst + Tungsten | | **类型安全** | 运行时检查 | 无 | 编译时检查(Scala) | | **适用场景** | 非结构化数据、复杂逻辑| 结构化数据、SQL分析 | 类型安全的结构化数据 | --- ### § 使用场景建议 1. **RDD**:需要手动优化分区/容错,或处理非结构化数据(如日志清洗)。 2. **DataFrame**:结构化数据分析(如SQL查询、聚合统计),或需要跨语言使用(Python优先)。 3. **DataSet**:Scala/Java项目中需类型安全且高效的计算(如复杂业务逻辑)[^4]。 --- §§ 相关问题 §§ 1. 为什么DataFrameRDD执行效率更高? 2. 如何将RDD转换为DataFrame? 3. DataSet在Scala中的类型安全是如何实现的? 4. Spark SQL是否支持直接操作DataSet? 5. 这三种数据结构在Spark版本演进中的关系是什么? --- : RDD一般和spark mlib同时使用,不支持sparksql操作。DataFrame提供了结构信息(schema),而RDD是分布式Java对象的集合。 [^2]: RDDDataFrameDataset各有优势,需根据场景选择。DataFrame以列形式组织数据,支持更高级的抽象。 : DataFrame允许添加数据结构到分布式数据集合,类似于关系数据库的表。 : RDDDataFrameDataSet分别对应Spark 1.0、1.3、1.6版本,逐步演进为更高效和类型安全的抽象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值