首页/数据/数据工程与 ETL 速查/PySpark 读写与转换最小示例
管道基础52 条

PySpark 读写与转换最小示例

PySpark 把 Spark 能力带入 Python:读列存、按列过滤聚合、写出分区表;DataFrame API 与 SQL 可以混用。

PySpark 读写是什么

PySpark 把 Spark 的分布式计算能力带进 Python:用 DataFrame API 读列存文件、做过滤聚合,再按分区写出结果表,也可以在同一个会话里混用 SQL。它的价值在于把 ETL 逻辑写成一段可调试的脚本,配合调度器就能成为离线管道的执行体。底层仍是 JVM 引擎,Python 侧通过 py4j 通信,因此自定义 UDF 的开销要高于内置函数。

基本信息

执行入口SparkSession.builder.appName(...).getOrCreate()
读取接口spark.read.parquet / csv / orc / jdbc
写出接口df.write.mode(...).partitionBy('dt').parquet(path)
写入模式append 追加、overwrite 覆盖、errorifexists、ignore
环境要求与集群一致的 Spark 版本、匹配的 Python 版本

按渠道汇总示例

按渠道汇总示例
from pyspark.sql import SparkSession
from pyspark.sql import functions as F

spark = SparkSession.builder.appName('orders_etl').getOrCreate()
df = spark.read.parquet('s3a://lake/curated/dwd/orders/dt=2026-10-11')
result = (df.filter('amount > 0')                 # 先过滤,减少后续扫描与聚合量
            .withColumn('dt', F.lit('2026-10-11')) # 分区列要显式补上
            .groupBy('channel')
            .agg(F.sum('amount').alias('amount_sum'),
                 F.countDistinct('order_id').alias('order_cnt')))
result.write.mode('overwrite').partitionBy('dt') \
      .parquet('s3a://lake/marts/ads/orders_channel_daily')  # 目标必须与上游隔离

典型使用场景

  • 每日离线 ETL:读上游明细分区、清洗聚合后写入集市表
  • 数据探查:临时读一批数据看分布、找空值与异常值,不再依赖抽样脚本
  • 表格式转换:Parquet 转 Iceberg、CSV 转 ORC 这类格式统一工作
  • 回补历史:按日期循环重跑指定分区,覆盖旧结果
  • 小规模特征计算:直接用 DataFrame 做 join 与窗口聚合

常见参数读法

项作用注意
mode控制目标路径已存在时的行为overwrite 会删除整个目标目录
partitionBy按列写成分区目录列必须已存在于 DataFrame 中
repartition/coalesce调整写出文件数repartition 触发 shuffle,coalesce 不触发
spark.sql.shuffle.partitions聚合阶段的分区数直接决定输出文件数量
缓存级别复用中间结果避免重复计算只缓存在多分支复用时才划算
overwrite 会把目标路径下的内容整体替换;如果目标写成与上游共享的目录,等于把上游数据一起删掉。不确定时先写临时目录,再由调度做切换。
Python UDF 需要逐行跨进程序列化,性能明显低于内置函数;能用 functions 里的表达式解决就不要写 UDF,必须写时优先考虑 pandas UDF。

易错点

  • 分区列在写之前要先存在于 DataFrame(如补 dt 字段),否则会写失败或全部落到根目录
  • 小批频繁写同一路径会积累小文件,需配合合并与重分区
  • overwrite 与上游共享目录时直接删数据,恢复只能依赖备份或重跑上游
  • 本地 Python 版本与集群 executor 不一致,UDF 会报找不到模块或语法不兼容
  • 把 driver 上定义的大对象直接闭包进 UDF,序列化开销与内存占用都会失控

数据来源与参考

  • Apache Spark 官方文档:PySpark DataFrame API(read/write)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌