
问题陈述:
在仅有 8GB 内存的一台 Databricks Worker 上,将一张超过 1 亿条记录的 Oracle 表迁移到 Snowflake,需要一种高度优化、具备内存感知的方案,以避免失败并确保在严格的 2 小时时限内稳定执行。传统方法存在发生内存不足错误和资源利用低效的风险,因此需要一种策略,在无需额外增加集群资源的前提下,优先实现受控的数据流式处理、尽可能小的内存占用以及高效的写入操作。(使用 Databricks、PyArrow 和 Native Spark)
❌ 常见错误:
使用单线程的 Pandas to_sql() = 必然触及内存上限并失败。
未调优的直接 JDBC 读取 = 缓慢且不稳定。
✅ 优化策略:
1.来源:Oracle 并行读取
调优 JDBC 的 fetchsize 与 defaultRowPrefetch.
计算并限制分区数以获得最佳并行度。
使用谓词下推以高效进行数据切分。
2.暂存:DBFS 上的 Snappy Parquet
重新分区以避免小文件。
写入 Snappy Parquet 以发挥列式效率。
* 避免小文件—合理使用 coalesce() 或 repartition()
* Parquet 块大小 128MB
创建稳定的分布式检查点。
3.处理:用 PyArrow 分块,而非 Pandas
按*row groups**迭代,而不是一次处理整个数据集。
使用 pyarrow.parquet.ParquetFile() 打开文件
通过.read_row_group() or .read_raw_group()读取每个分组
*至关重要的是跳过 Pandas 转换**,以避免 driver 端 OOM.
*直接转换为 Spark DataFrame,以进行分布式处理。
4.加载:使用 Native Spark Writer 至 Snowflake
使用 spark-snowflake 连接器进行并行、高吞吐写入。
利用 Snowflake 的 Apache Arrow 集成以提升速度。
5.稳定性:显式内存清理
在每个分块处理后删除 DataFrame 引用。
*删除 DataFrame 对象
*显式丢弃所有列以释放内存
手动触发垃圾回收 (
gc.collect()
).防止长时作业中的内存泄漏。结果:在单个 8GB worker 节点上对 1 亿+记录实现稳定执行,并在可预测的 2 小时窗口内完成(Approx)。
声明:本演示中所表达的观点和意见仅代表作者个人,并不必然反映 Novartis 或其任何附属机构或管理人员的官方政策或立场。
原文地址:
评论