SparkSQL 之 DataFrame 与 DataSet 及实操演练

摘要:从 RDD 到 DataFrame 再到 DataSet,Spark 的 API 经历了三次重大进化。DataFrame = DataSetRow(有 Schema 但无类型),DataSetT = RDD 的类型安全 + DataFrame 的 Catalyst 优化。本文从三层 API 架构全景、RDD/DataFrame/DataSet 创建与互转、Catalyst 优化器四阶段、Encoder 序列化机制、生产环境最佳实践五个维度,配合 1 张原创深色架构图 + 完整可运行实操代码,助你彻底掌握 SparkSQL 的 API 体系。

关键词:SparkSQL, DataFrame, DataSet, RDD, Catalyst, Encoder, SparkSession, Tungsten


一、开篇:SparkSession --- 万物入口

scala 复制代码
import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder()
  .appName("SparkSQL Demo")
  .master("local[*]")
  .config("spark.sql.shuffle.partitions", "4")
  .getOrCreate()

import spark.implicits._  // 启用 RDD → DF 隐式转换 + Encoder

二、三层 API 架构全景图

核心关系

scala 复制代码
// DataFrame 本质
type DataFrame = DataSet[Row]  // DataFrame 就是无类型的 DataSet

// 互转关系
val rdd: RDD[Person] = ...
val df: DataFrame = rdd.toDF()          // RDD → DataFrame
val rdd2: RDD[Row] = df.rdd             // DataFrame → RDD
val ds: DataSet[Person] = df.as[Person] // DataFrame → DataSet (类型安全)
val df3: DataFrame = ds.toDF()           // DataSet → DataFrame

三、RDD vs DataFrame vs DataSet 对比

维度 RDD DataFrame DataSetT
版本 Spark 1.0 Spark 1.3 Spark 1.6
Schema
类型安全 ✅ 编译期 ❌ 运行时 ✅ 编译期
优化器 ✅ Catalyst ✅ Catalyst
序列化 Java/Kryo Encoder (Tungsten) Encoder (Tungsten)
API 风格 函数式 SQL/DSL 函数式+SQL
Python ❌ (仅 Scala/Java)
推荐度 特殊场景 快速分析 ⭐ 生产首选

四、DataFrame 实操

4.1 创建 DataFrame

scala 复制代码
// 方式 1: 从 JSON/CSV/Parquet 读取
val df = spark.read.json("hdfs:///data/people.json")
val df2 = spark.read.option("header", "true").csv("hdfs:///data/people.csv")

// 方式 2: 从 RDD + Schema 创建
val rdd = spark.sparkContext.parallelize(Seq(
  ("Alice", 28), ("Bob", 35), ("Charlie", 42)
))
val df3 = rdd.toDF("name", "age")

// 方式 3: SQL 查询
df.createOrReplaceTempView("people")
val df4 = spark.sql("SELECT name, age FROM people WHERE age > 30")

4.2 DataFrame 操作

scala 复制代码
// DSL 风格
df.select($"name", $"age" + 1)
  .where($"age" > 30)
  .groupBy($"name")
  .agg(avg($"age").as("avg_age"))
  .orderBy($"avg_age".desc)
  .show()

// SQL 风格
spark.sql("""
  SELECT name, AVG(age) as avg_age
  FROM people WHERE age > 30
  GROUP BY name ORDER BY avg_age DESC
""")

五、DataSet 实操(类型安全)

scala 复制代码
// 定义 case class
case class Person(name: String, age: Int)

// 从 DataFrame 转 DataSet
import spark.implicits._
val ds: DataSet[Person] = df.as[Person]

// DataSet 类型安全操作
ds.filter(_.age > 30)           // 编译期检查:_.age 是 Int
  .map(p => (p.name, p.age + 1)) // 类型安全的 map
  .groupByKey(_._1)
  .agg(avg($"_2").as[Double])
  .show()

六、Encoder 序列化(比 Kryo 快)

scala 复制代码
// Encoder 自动生成(case class)
val ds = spark.read.json("...").as[Person]
// 内部使用 Tungsten 堆外内存 + 二进制格式 → 免 Java/Kryo 序列化

// 显式创建 Encoder
import org.apache.spark.sql.Encoders
val encoder = Encoders.product[Person]
val ds2 = spark.createDataset(Seq(Person("A", 1)))(encoder)

七、Catalyst 优化器四阶段

java 复制代码
SQL/DSL 文本 → ① Parser → Unresolved Logical Plan
            → ② Analyzer → Resolved Logical Plan (绑定表/列)
            → ③ Optimizer → Optimized Logical Plan (谓词下推/列裁剪)
            → ④ Planner → Physical Plan (RDD DAG)

八、生产最佳实践

bash 复制代码
# 推荐: DataSet[T] (Scala) / DataFrame (Python)
# 配置关键参数
--conf spark.sql.adaptive.enabled=true
--conf spark.sql.shuffle.partitions=200
--conf spark.sql.autoBroadcastJoinThreshold=10MB
--conf spark.sql.parquet.filterPushdown=true

九、总结

要点 总结
入口 SparkSession 替代 SQLContext
DataFrame = DataSetRow,有 Schema 无类型
DataSet = RDD + Encoder + Catalyst,生产首选
Encoder Tungsten 堆外,比 Kryo 更快
Python 只有 DataFrame,无 DataSet

金句:RDD 给了你灵活的自由,DataFrame 给了你 SQL 的优雅,DataSet 给了你编译期的安全------三者是一个进化链,而不是互斥的选项。


作者:starzy | AI Data Engineer / 大数据技术实践者

博客:blog.starzy.cn | GitHub:starzy1990.github.io

专注 AI Agent · LangGraph · RAG · 大数据架构 · 数据工程实践

相关推荐
牛马之星8 分钟前
气体涡轮流量计哪家好?天然气流量计源头厂家推荐与选型指南
大数据
jinggongszh37 分钟前
欧盟电池护照背景下,电池制造企业如何构建MES数字化追溯体系
大数据·制造·mes系统·电池行业·生产制造执行系统
Allen_LVyingbo41 分钟前
医疗AI基础2026-构建可靠智能体的编程路径(上)
大数据·数据库·人工智能·python·自动化
熊野君1 小时前
第 7 章 AI时代产品经理新增能力
大数据·人工智能·经验分享·职场和发展·产品经理
ha_lydms2 小时前
HDFS 简介
大数据·hadoop·hdfs·yarn·调度·aliyun·计算
oort1232 小时前
OortCloud Token Plan
大数据·人工智能·开源
Sky1987star2 小时前
产品资料更新后,怎样让 AI 内容与客服同步生效?
大数据·人工智能
flyinsono2 小时前
单体宠物诊所数字化转型,选对管理系统少走弯路
大数据·人工智能·宠物
cxr8282 小时前
AI时代科学研究思维框架的适应性分析与检查清单构建
大数据·人工智能·认知框架
大大大大晴天2 小时前
每天认识一个组件:统一 Shuffle 引擎Apache Uniffle
大数据