我处于类似the one mentioned here的情况 . 问题没有得到满意的答复 . 此外,我处理的数据较少(每天约1G) .
我的情况:我已经有一定数量的数据(~500G)可用作镶木地板(这是商定的“存储格式”),我定期进行增量更新 . 我希望以后能够处理ETL部分以及分析部分 .
为了能够有效地生成某些“中间数据产品”的更新,我看到三个选项:
-
使用 append mode 保存,保持 diff dataset ,直到创建所有数据产品
-
使用 append mode 保存,添加一个额外的列
upload_timestamp
-
将每个更新保存到单独的文件夹,例如:
data
+- part_001
| +- various_files.parquet
+- part_002
| +- various_files.parquet
+- ...
这样,可以使用 data/*
作为 read.parquet()
的路径读取整个数据集 .
我倾向于采用最后一种方法,也因为存在注释(证据?),当分区数量增加时,追加模式会导致问题(例如参见this SO question) .
So my question: 在创建像这样的数据集结构时有一些严重的缺点吗?显然,Spark在阅读多个文件夹时需要进行"some"合并/排序,但除此之外?
我使用的是Spark 2.1.0 .
2 回答
Nathan Marz,前Twitter和Lambda Architecture的作者,描述了在批处理层中存储数据的垂直分区过程,这是真实的来源,并包含架构所见过的所有数据 . 此主数据集是不可变的并且仅附加 . 垂直分区只是一个奇特的名称,用于将数据分类到单独的文件夹中 .
这正是您在第三个选项中描述的内容 .
这样做可以显着提高性能,因为在主数据集上执行的功能只能访问与计算相关的那些数据 . 这使得批量查询和服务层中的索引创建速度更快 . 文件夹的名称由您决定,但通常涉及时间戳组件 .
无论您是否构建Lambda架构,垂直分区都将使您的分析更加高效 .
我注意到目录中的文件夹数量越多,
spark.read
执行的时间就越长,因为spark对数据/元数据进行采样以确定模式 . 但这可能是你必须要处理的必然性 .如果你添加一个
upload-timestamp
甚至更好的upload-date-hour
和分区,它自然会写入该文件夹 . 如果有可能在给定的小时内有多组文件,请确保通过api访问写入,确保在写入之前对现有数据执行union
.