2、Spark环境准备:Spark安装与配置、SparkSession初始化、数据读取基础
在开始特征工程样本偏差校验之前,必须搭建一个稳定、可复现的Spark运行环境。本章将指导你完成从Spark安装到数据读取的全流程,确保后续所有校验逻辑都能在统一的计算框架上执行。
2.1 Spark安装与配置
Spark支持多种部署模式:本地模式(Local)、独立集群模式(Standalone)、YARN模式以及Kubernetes模式。对于特征工程样本偏差校验的开发与测试阶段,推荐使用本地模式,它无需额外集群资源,即可快速验证代码逻辑。
| 部署模式 | 适用场景 | 资源管理 | 推荐用途 |
|---|---|---|---|
| Local | 单机开发、单元测试 | 本机CPU/内存 | 原型验证、小规模数据校验 |
| Standalone | 小型集群 | Spark内置Master/Worker | 团队协作、中等规模测试 |
| YARN | 生产环境、大数据量 | Hadoop YARN | 全量数据偏差校验 |
| Kubernetes | 容器化部署 | K8s Pod | 云原生环境 |
推荐配置:本教程所有示例均基于 Spark 3.4+ 与 Scala 2.12/2.13。建议在开发机上至少分配 4GB 内存给 Spark Driver,以应对样本偏差校验过程中的聚合计算。
2.1.1 下载与安装步骤
- 下载Spark:访问
https://spark.apache.org/downloads.html,选择预编译好的Hadoop版本(如spark-3.4.1-bin-hadoop3.tgz)。 - 解压安装:将压缩包解压至指定目录,例如
/opt/spark或C:\spark。 - 配置环境变量:设置
SPARK_HOME并将$SPARK_HOME/bin加入PATH。 - 验证安装:在终端执行
spark-shell --version,确认版本信息正确输出。
# Linux/macOS 环境变量配置示例
export SPARK_HOME=/opt/spark
export PATH=$SPARK_HOME/bin:$PATH
# 验证安装
spark-shell --version
2.2 SparkSession初始化
SparkSession是Spark 2.0+的统一入口点,它整合了SQLContext、HiveContext和StreamingContext的功能。在样本偏差校验任务中,我们通过SparkSession来配置资源、读取数据源以及执行DataFrame操作。
核心原则:每个Spark应用程序只应创建一个SparkSession实例。在特征工程流水线中,建议将SparkSession的初始化放在最外层,作为全局共享对象。
2.2.1 标准初始化模板
import org.apache.spark.sql.SparkSession
val spark = SparkSession.builder()
.appName("SampleBiasValidation")
.master("local[*]") // 本地模式,使用所有可用核心
.config("spark.sql.shuffle.partitions", "10") // 小数据量时减少分区数
.config("spark.sql.adaptive.enabled", "true") // 启用自适应查询执行
.getOrCreate()
// 设置日志级别,减少控制台干扰
spark.sparkContext.setLogLevel("WARN")
注意:在本地模式使用
local[*] 时,Spark会占用所有CPU核心。如果开发机资源有限,建议指定核心数,例如 local[2],避免影响其他进程。
2.2.2 关键配置参数说明
| 参数名 | 默认值 | 偏差校验场景推荐值 | 说明 |
|---|---|---|---|
spark.sql.shuffle.partitions |
200 | 10~50 | 控制聚合、join等操作的并行度;小数据量时降低该值可减少任务调度开销 |
spark.sql.adaptive.enabled |
false | true | 自适应查询执行,动态调整分区和join策略,对偏差校验中的倾斜数据友好 |
spark.sql.adaptive.coalescePartitions.enabled |
true | true | 自动合并小分区,减少文件碎片 |
spark.driver.memory |
1g | 4g~8g | Driver端内存,用于收集统计信息和缓存小表 |
2.3 数据读取基础
样本偏差校验的第一步是加载数据。Spark支持从多种数据源读取数据,包括CSV、Parquet、JSON、Avro以及JDBC等。在特征工程场景中,最常用的格式是Parquet(列式存储、压缩率高)和CSV(通用性强、易于查看)。
2.3.1 读取CSV文件
// 读取CSV文件,自动推断Schema
val dfCsv = spark.read
.option("header", "true") // 第一行为列名
.option("inferSchema", "true") // 自动推断数据类型
.option("delimiter", ",") // 分隔符
.option("mode", "PERMISSIVE") // 容错模式,损坏行置为null
.csv("path/to/sample_data.csv")
dfCsv.printSchema()
dfCsv.show(5, truncate = false)
2.3.2 读取Parquet文件
// 读取Parquet文件(自带Schema,无需推断)
val dfParquet = spark.read
.option("mergeSchema", "true") // 合并多个Parquet文件的Schema
.parquet("path/to/feature_data/")
dfParquet.printSchema()
println(s"总记录数:${dfParquet.count()}")
2.3.3 读取JSON文件
// 读取多行JSON文件
val dfJson = spark.read
.option("multiLine", "true") // 一个JSON对象跨多行
.json("path/to/nested_data.json")
// 展平嵌套结构
import org.apache.spark.sql.functions._
val dfFlattened = dfJson.select(
col("id"),
col("features.*") // 展开features结构体
)
性能建议:在读取大规模样本数据时,优先使用Parquet格式。Parquet不仅存储效率高,而且内置Schema信息,能避免CSV的Schema推断开销。对于偏差校验任务,建议将原始数据统一转换为Parquet格式后再进行分析。
2.4 数据读取最佳实践
- Schema预定义:对于生产环境,建议手动定义Schema而非使用
inferSchema,避免每次读取都触发额外的数据扫描。 - 分区读取:如果数据按日期或地域分区,使用
spark.read.parquet("base_path/")自动发现分区列。 - 采样与缓存:在偏差校验初期,使用
.sample(withReplacement = false, fraction = 0.1)进行数据采样,配合.cache()加速迭代分析。 - 空值处理:读取时设置
.option("nullValue", "NA")或.option("nanValue", "NaN"),统一空值表示。
// 手动定义Schema示例
import org.apache.spark.sql.types._
val schema = StructType(Array(
StructField("user_id", StringType, nullable = false),
StructField("age", IntegerType, nullable = true),
StructField("income", DoubleType, nullable = true),
StructField("label", IntegerType, nullable = false)
))
val df = spark.read
.schema(schema)
.option("header", "true")
.csv("path/to/users.csv")
常见陷阱:使用
inferSchema 时,Spark会扫描所有数据以推断列类型。对于包含数百万行的大文件,这将导致额外的I/O开销。建议在开发阶段先用 sample 推断,再将结果固化到代码中。