apache-spark - 镶木地板内部和火花
问题描述
我有一个由每日批处理创建的数据帧,该批处理在特定日期运行,然后保存在 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)
如您所见,我没有对数据框进行分区,因为它只包含一个日期。
因此,例如,第一天的第一个文件将存储在文件夹中
交易/2019/08/25
然后第二天,它会在文件夹中
交易/2019/08/26
问题是,当所有数据都放好后,日期上的过滤谓词是否仍会被下推,HDFS 会知道在哪里找到数据而不是进行全面扫描吗?
或者即使我节省了一天,我仍然必须使用 Partition by option 来编写,只是为了让 Spark 在阅读时理解并将其推送到 HDFS 并且 HDFS 也知道在哪里找到它(而不是全扫描)?
问题的下一部分是:
当我查看存储 parquet 文件的文件夹时,我看到很多小的“part-****.snappy.parquet 文件。我通过阅读这里的一些论坛问题了解到我必须使用“重新分区”如果我必须减少文件数量的选项。但问题是 - 是否有必要?我读到太多的小文件当然会影响性能,所以一种选择可能是将其保存为 128 MB 的块(如果我我不确定数据将如何在下游使用(目前意味着哪些列),这样 HDFS 中的 NameNode 不会负担过重,我们也没有太大的文件。这是否也适用于这些“活泼的镶木地板分区文件” “ 还?
太多的概念,我仍在努力寻找将这些数据帧存储为镶木地板的最佳解决方案,因此任何见解都将不胜感激。
解决方案
如果数据存储为,Spark 会知道从哪里获取数据
root/
date=ddmmyy/
date=dd1mm1yy1/
...
=
标志很重要。谓词下推不能有任意目录结构。它必须采用上述格式。
在你的例子中
你需要存储类似的东西
root/
Trades=2019/08/25
Trades=2019/08/26
Spark 利用 hive 分区发现机制来检测表中的分区。Hive 分区需要以特定方式放置数据。
来到你问题的下一部分。无论文件的类型如何,保留小文件HDFS
都是非常糟糕的。是的,对于 snappy 分区文件来说确实如此。您应该使用repartition
orcoalesce
函数来保持文件大小接近 128 MB。
namenode 的职责是跟踪 HDFS 中的所有文件。HDFS 中的块大小为 128 MB。因此,请尽量保持.parquet
文件大小接近 128 MB,但不要更多。如果你保留得更多,HDFS 将使用 2 个块来表示数据。
推荐阅读
- logging - 防止在 Resilience4j Retry 的 onException() 上进行详细日志记录
- python - python如何继承父栈
- jenkins - JenkinsFile(管道脚本)错误:语法错误:未终止的引号字符串
- python - 在链接中添加字符
- windows - 在 Windows 上查询 chmod 值的 git 索引
- python - 在 Python 中进行基于方面的情感分析时需要有关否定处理的建议
- c# - 使用 foreach 获取中继器数据它总是返回第一项
- python - Python:计算句子中 D 的数量,返回 AttributeError 消息
- python - 复制没有相同 id 的类数组
- javascript - 如何使用 Node 将 JavaScript 文件解析为对象