apache-spark - Parquet 压缩性能分组与平面数据
问题描述
无法从网上得到直接的答案。考虑以下数据场景:我有包含 user_id 和用户活动时间戳的数据:
val bigData = Seq( ( "id3",12),
("id1",55),
("id1",59),
("id1",50),
("id2",51),
("id3",52),
("id2",53),
("id1",54),
("id2", 34)).toDF("user_id", "ts")
所以原始的 DataFrame 看起来像这样:
+-------+---+
|user_id| ts|
+-------+---+
| id3| 12|
| id1| 55|
| id1| 59|
| id1| 50|
| id2| 51|
| id3| 52|
| id2| 53|
| id1| 54|
| id2| 34|
+-------+---+
例如,这就是我将写入 HDFS\S3 的内容。
但是我无法保存按用户分组的数据,例如:
bigData.groupBy("user_id").agg(collect_list("ts") as "ts")
导致:
+-------+----------------+
|user_id| ts|
+-------+----------------+
| id3| [12, 52]|
| id1|[55, 59, 50, 54]|
| id2| [51, 53, 34]|
+-------+----------------+
对于哪种方法可以在文件系统上获得更好的存储/压缩,我可以得到一个决定性的答案。分组方法看起来(直观地)更好的存储/压缩方式。
任何人都知道是否有绝对的方法或知道关于这个主题的任何基准或文章?
解决方案
让我们考虑以扁平结构存储数据的第一种情况。如果您对数据进行排序,id
那么相同的 id 将进入相同的分区。这将导致Parquet 字典压缩,从而减小大小。
此外,如果您ts
是有界的,那么镶木地板格式会保留基础并创建偏移量。
例如
50 51 52 60 are the ts
Parquet saves : base: 50, offset: 0, 1, 2, 8
如果偏移量可以用 2 个字节表示,这可能会节省更多空间。
其他格式也是有效的。但唯一的问题是,由于 parquet 是一种列格式,列值越大,parquet 将为其余列值创建填充
例如
ts
----
[20],
[20,40,60,70,80]
parquet 将为 20 创建填充并将其保持为[20,40,60,70,80]
.
我建议您对数据集进行各种实验,测量大小并检查镶木地板页脚。您将深入了解 parquet 如何为您的应用程序存储数据。问题是数据大小将取决于基础数据,因此我们可能无法得到确凿的答案。
推荐阅读
- python-3.x - Pytorch 中的内存泄漏:对象检测
- python - 在我的虚拟环境中无法识别 Python 'wikipedia' 模块
- python - 用变量替换计算python上的表达式
- android - 清单合并异常:SAXParseException
- flutter - 为什么 Flutter 运行需要永远?
- oracle11g - Oracle:从每第 n 条记录的 id 列中获取范围
- javascript - 一旦解除了boostrap vue警报,它就不再工作了
- java - SQLITE_ERROR SQL 错误或缺少数据库(没有这样的表:用户)
- wordpress - 使用 wamp 将 wordpress 导入到 localhost 时,localhost 拒绝连接
- python - 逻辑回归 - 计算每个属性对最终概率的贡献程度