0%

spark自定义函数详解:UDF 与 UDAF 实战指南

在 Spark SQL 中,内置函数(如 sumconcat)可满足多数基础需求,但复杂业务场景往往需要自定义逻辑。Spark 支持两种核心自定义函数:用户定义函数(UDF)用户定义聚合函数(UDAF)。本文将深入解析两者的实现原理、使用场景及实战案例,帮助你灵活扩展 Spark 的数据处理能力。

自定义函数概述

为什么需要自定义函数?

  • 业务个性化:内置函数无法覆盖复杂业务逻辑(如特殊格式转换、自定义指标计算);
  • 代码复用:将常用逻辑封装为函数,避免重复开发;
  • 简化 SQL:用自定义函数替代复杂 SQL 子查询,提升可读性。

自定义函数的类型

  • UDF(User-Defined Function)一行输入 → 一行输出,如字符串拼接、格式转换;
  • UDAF(User-Defined Aggregate Function)多行输入 → 一行输出,如自定义平均值、加权求和。

UDF:用户定义函数(单行处理)

UDF 是最常用的自定义函数类型,用于对单条记录的字段进行转换或计算。其核心是接收一个或多个输入值,返回单个输出值。

UDF 的定义与注册

Scala 实现 UDF

通过 spark.udf.register 方法注册 UDF,支持匿名函数或方法引用:

阅读全文 »

DataSet编程详解:强类型结构化数据处理的利器

DataSet 是 Spark SQL 中融合了 DataFrame 结构化特性与 RDD 强类型优势的高级抽象。作为 DataFrame 的扩展,DataSet 提供了编译时类型安全,让开发者能以更直观的方式处理复杂领域对象。本文将深入解析 DataSet 的创建、操作、特性及最佳实践,帮助你充分利用这一强大工具。

DataSet 的核心特性与价值

DataSet 与 DataFrame、RDD 的对比

DataSet 是 Spark 1.6 引入的新抽象,填补了 DataFrame 弱类型和 RDD 缺乏结构化优化的空白:

特性 RDD[T] DataFrame(DataSet[Row]) DataSet[T]
类型安全 强类型(编译时检查) 弱类型(运行时检查) 强类型(编译时检查)
数据结构 无 schema,依赖类定义 有 schema,Row 类型无具体字段名 有 schema,与类字段一一对应
优化支持 无自动优化 支持 Catalyst 优化器 支持 Catalyst 优化器
API 风格 函数式编程(map、filter) SQL 风格(select、where) 函数式 + SQL 风格结合
适用场景 非结构化数据处理 通用结构化数据查询 复杂业务对象处理、类型安全需求

DataSet 的核心优势

  • 编译时类型检查:避免因字段名拼写错误或类型不匹配导致的运行时异常;
  • 直观的对象操作:直接通过类的字段名访问数据(如 user.name),无需解析 Row 对象;
  • 优化的执行计划:继承 DataFrame 的 Catalyst 优化器,兼顾类型安全与性能;
  • 与 Scala/Java 无缝集成:支持自定义类和样例类,贴合面向对象编程习惯。

DataSet 的创建方式

DataSet 的创建依赖类型信息,通常需要定义样例类(Case Class)或 Java Bean 作为数据结构模板。以下是常见创建方式:

从序列(Seq)创建

通过 toDS() 方法将样例类序列转换为 DataSet:

阅读全文 »

DataFrame编程全解析:结构化数据处理的核心抽象

DataFrame 是 Spark SQL 的核心抽象,它将关系型数据库的结构化查询能力与 Spark 的分布式计算能力相结合,为开发者提供了高效、灵活的数据处理方式。本文将深入探讨 DataFrame 的创建、转换、操作及性能优化,帮助你全面掌握这一强大工具。

DataFrame 基础概念与核心特性

DataFrame 与 RDD 的本质区别

特性 RDD DataFrame
数据结构 无 schema,仅存储对象集合 有 schema,明确列名和类型
优化机制 依赖手动优化,缺乏查询分析 自动优化执行计划(Catalyst 优化器)
计算方式 基于函数式编程(map、filter 等) 基于关系代数(select、join、groupBy)
序列化方式 对象序列化,开销大 列式存储(如 Parquet),节省空间
适用场景 非结构化数据(如日志、文本) 结构化数据(如数据库表、CSV)

Schema 元信息的重要性

Schema 定义了 DataFrame 各列的名称和类型,使 Spark 能够:

  • 优化内存使用:通过列式存储和类型推断,减少内存占用;
  • 加速查询执行:直接定位所需列,避免全量扫描;
  • 提供类型安全:编译时检查列名和类型,提前发现错误。

DataFrame 的创建与转换

创建 DataFrame 的主要方式

从文件数据源读取

支持 CSV、JSON、Parquet、ORC 等多种格式:

阅读全文 »

sparkSQL详解:结构化数据处理的核心引擎

Spark SQL 是 Spark 生态中专门用于结构化数据处理的模块,它整合了关系型数据库的 SQL 语法与 Spark 的分布式计算能力,为开发者提供了高效、灵活的结构化数据处理方案。本文将从 Spark SQL 的起源、核心抽象(DataFrame 与 DataSet)、特性优势及基础使用入手,全面解析这一核心模块。

Spark SQL 的起源与演进

诞生背景

在 Spark 早期版本中,RDD 作为核心抽象,虽能处理分布式数据,但缺乏对结构化数据的原生支持。开发者需手动解析数据结构(如 CSV、JSON),编写大量样板代码。为解决这一问题,Spark 团队推出 Spark SQL,目标是:

  • 提供 SQL 接口,降低数据分析门槛(让熟悉 SQL 的开发者快速上手);
  • 支持结构化数据的高效处理,整合 Spark 的分布式计算能力。

发展历程

  • 早期版本(Shark):基于 Hive 构建,依赖 Hive 的元数据和查询优化器,但受限于 Hive 的 MapReduce 执行引擎,性能提升有限。
  • Spark SQL 独立化:为摆脱对 Hive 的依赖,Spark 1.0 后重构为独立模块,引入 Catalyst 优化器和 Tungsten 执行引擎,性能大幅提升。
  • 统一数据抽象:Spark 1.3 引入 DataFrame,Spark 1.6 引入 DataSet,形成 “RDD + DataFrame + DataSet” 的多层次 API 体系。

Spark SQL 的核心特性

多数据源兼容

Spark SQL 支持多种结构化数据源的读写,无需手动转换格式:

  • 文件格式:Parquet、ORC、CSV、JSON、Text 等;
  • 数据库:Hive、MySQL、PostgreSQL 等(通过 JDBC);
  • 流数据:与 Spark Streaming 整合,处理实时结构化数据。

高性能优化

Spark SQL 引入多项核心技术提升性能:

  • Catalyst 优化器:基于规则和成本的查询优化器,自动优化 SQL 执行计划;
  • Tungsten 执行引擎:通过内存管理优化和代码生成(Code Generation)提升执行效率;
  • 列式存储:默认使用 Parquet 列式存储格式,减少 I/O 开销。

多接口支持

Spark SQL 提供多种编程接口,适配不同开发习惯:

阅读全文 »

大 M 法:将非线性约束线性化的线性规划技巧

在实际优化问题中,常遇到 “要么不做,要么必须达到某个阈值” 的非线性约束(如广告投放 “要么不投,要么至少投 100cpm”)。大 M 法(Big M Method)通过引入二进制变量和一个足够大的常数 M,将这类非线性约束转化为线性约束,从而用线性规划求解。本文结合广告投放场景,详细解析大 M 法的应用。

问题场景与核心约束

场景定义

  • 需投放广告至至少 2 个城市,共 3 个城市可选(记为城市 1、2、3)。
  • 每个城市的投放规则:要么不投(投放量 = 0),要么至少投 100cpm(cpm 为投放单位)。
  • 总投放量≥3000cpm,目标是最小化总成本(城市 1、2、3 的单位成本分别为 5、6、23)。

核心非线性约束

每个城市的投放量c_i(i=1,2,3)存在 “0 或≥100” 的非线性选择,即:
c_i = 0 或 c_i ≥ 100

这类约束无法直接用线性规划表达,需通过大 M 法转化。

大 M 法的核心思路

1. 引入二进制变量

为每个城市引入二进制变量ca_i(0 或 1),表示投放决策:

阅读全文 »