无法真正从网上得到直接的答案。 请考虑以下数据方案: 我有包含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]|
+-------+----------------+
对于哪种方法可以在文件系统上获得更好的存储/压缩,我可以得到决定性的答案。分组方法看起来(直观)更好的存储/混合性。
有人知道是否有绝对的方法,或者知道关于此主题的任何基准或文章吗?
答案 0 :(得分:1)
让我们考虑第一种情况,即数据以平面结构存储。如果使用id
对数据进行排序,则相同的ID将进入相同的分区。这将导致Parquet dictionary compression减小尺寸。
此外,如果您的ts
受限制,则实木复合地板格式将保留基础并创建偏移量。
例如
50 51 52 60 are the ts
Parquet saves : base: 50, offset: 0, 1, 2, 8
如果偏移量可以2字节表示,则可以节省更多空间。
其他格式也有效。但是唯一的是,由于镶木地板是柱状格式,因此列值越大,镶木地板将为其余的列值创建填充
例如
ts
----
[20],
[20,40,60,70,80]
实木复合地板将为20创建填充,并将其保留为[20,40,60,70,80]
的相同大小。
我建议您对数据集进行各种实验,测量尺寸并检查镶木地板的页脚。您将获得深刻的见解,镶木地板如何为您的应用程序存储数据。问题是数据大小将取决于基础数据,因此我们可能无法得出结论性的答案。