【问题标题】:Very slow parquet reads非常慢的镶木地板读取
【发布时间】:2018-04-13 16:27:56
【问题描述】:

我正在尝试从两个不同的位置 A 和 B 读取镶木地板文件。它们都是 GCP 中的镶木地板文件,架构中的列数大致相同(80 - 90,主要是字符串)。 B 的文件大小和记录数非常小(大约比 A 小 5 个数量级)。但是从 GS 读取 A 所需的时间大致相同。我想知道为什么会这样。

scala> show_timing{spark.read.parquet("gs://bucket-name/tables/A/year=2018/month=4/day=5/*")}
Time elapsed: 34862525 microsecs
res5: org.apache.spark.sql.DataFrame = [a1: string, a2: string ...     84 more fields]

scala> show_timing{spark.read.parquet("gs://bucket-name/tables/B/year=2018/month=4/day=5/*")}
Time elapsed: 25094417 microsecs
res6: org.apache.spark.sql.DataFrame = [b1: string,     b2: string ... 81 more fields]

scala> res5.count()
res7: Long = 2404444736

scala> res6.count()
res8: Long = 98787

我的 spark 版本是 2.2。我知道这不是很多信息。但我不太确定还有什么要调查的。

【问题讨论】:

  • 每种情况下分区和执行器的数量是多少?
  • 两台相同的 gcp n1-standard-8(8 核)机器具有 60 个工作节点。 --executor-cores--num-executors 没有额外设置。
  • day=5/* 中单个 .parquet 文件的数量是多少?例如,如果那里只有一个文件,尽管您有很多可用的文件,但只有一个执行者会读取它。另一方面,如果有成千上万的小文件,打开它们的成本可能太高,在将数据保存到此分区时,将它们合并为少量较大的文件是值得的。另外,在 Spark UI 中查看是否所有执行器在读取阶段都被平等地利用。
  • 对于案例 B,它每小时一个文件。所以每天24个。每个文件的大小小于 2MB。在案例 A 中,每小时大约有 200 个文件,每个文件 150 MB。差别比较大。我要增加每个核心的执行者,看看。

标签: scala apache-spark parquet


【解决方案1】:

原因是spark在执行read.parquet操作时实际上并没有读取数据,所以读取操作所用的时间大致相同。 readlazy,也就是说,只有当你执行一个动作时才会访问数据(比如 count)。我敢打赌这两个计数操作不会花费相同的时间!

read 执行时,它只读取 parquet 文件的元数据来计算架构,因此文件大小无关紧要。

看看 spark 中的转换与动作。有些操作会触发计算(因此会触发 I/O 来实现 rdd),有些则不会:https://spark.apache.org/docs/latest/rdd-programming-guide.html#rdd-operations

【讨论】:

  • 这当然是第一个也是最明显的解释。但如果你注意到时间本身,它就会大得不成比例。当我读取一个月的数据时,执行此命令大约需要 25 分钟。即使 spark 遍历所有文件以通过其惰性读取来确定模式,它也仅使用 30 x 24 文件这样做。每个文件大约2MB。没什么。集群也很大——大约有 360 个内核。时间只是没有意义。因此,我正在寻找其他解释。
猜你喜欢
  • 2020-04-22
  • 2021-08-27
  • 2019-08-04
  • 2018-12-20
  • 2022-06-16
  • 1970-01-01
  • 2019-05-07
  • 2019-09-23
  • 2017-12-27
相关资源
最近更新 更多