我有一个数据框,该数据框由每天运行的特定日期创建,然后保存在HDFS(Azure Data Lake Gen 2)中。
使用类似的方法保存
TradesWritePath="abfss://refined@"+datalakename+".dfs.core.windows.net/curated/clientscoredata/clientscoredatainput/Trades/" + TradeDatedt + "/Trades_" + tradedateInt + ".parquet"
tradesdf.write.mode("overwrite").parquet(TradesWritePath)
如您所见,我不对数据框进行分区,因为它仅包含一个日期。
例如,第一天的第一个文件将存储在文件夹中
Trades / 2019/08/25
然后第二天,它将在文件夹中
Trades / 2019/08/26
问题是,当所有数据都放入后,是否仍会下推基于日期的过滤谓词,HDFS是否会知道从何处查找数据而不是进行全面扫描?
或者即使我节省了一天的时间,我还是仍然必须使用Partition by Option进行写操作,这样Spark才能在读取时理解并将其下推到HDFS,而HDFS也知道在哪里可以找到它(而不是全扫描)? / p>
问题的下一部分是:
当我查看实木复合地板文件的存储文件夹时,我看到了很多小的“ part-****。snappy.parquet”文件。我通过阅读这里必须使用的一些论坛问题来理解如果必须减少文件数量,则使用“重新分区”选项。 但是问题是-是否有必要?我读到,太多的小文件当然会影响性能,因此一个选择可能是将其保存为128 MB的块(如果我不确定该如何在下游使用数据,则意味着现在是哪一列),这样HDFS中的NameNode不会负担过多,并且文件也不会太大。这是否也适用于这些“诱人的镶木地板分区文件”?
概念太多,我仍在努力寻找最好的解决方案,以将这些数据帧存储为拼花地板,因此,任何见识都将受到极大的赞赏。
答案 0 :(得分:1)
您不应创建自己的目录。
在编写实木复合地板时,请使用partition
按日期进行分区。它将自动处理目录的创建,并且在读取时不会扫描整个表。
对于问题的第二部分,是的,我们的想法是将每个分区保持在128MB左右,但是老实说,这不会花很多钱,您可以将默认分区保持为200。
答案 1 :(得分:0)
如果存储为
的数据,Spark会知道从哪里提取数据。root/
date=ddmmyy/
date=dd1mm1yy1/
...
=
符号很重要。您不能具有用于谓词下推的任意目录结构。必须采用上述格式。
在您的示例中
您需要存储
root/
Trades=2019/08/25
Trades=2019/08/26
Spark利用配置单元分区发现机制来检测表中的分区。配置单元分区要求以特定方式放置数据。
进入问题的下一部分。无论文件类型如何,将小文件都保存在HDFS
中是非常糟糕的。是的,对于分区分区文件来说确实如此。您应该使用repartition
或coalesce
函数将文件大小保持在128 MB附近。
namenode的职责是跟踪HDFS中的所有文件。 HDFS中的块大小为128 MB。因此,请尝试将.parquet
文件的大小保持在128 MB附近,但不要更多。如果保留更多,HDFS将使用2个块表示数据。