【问题标题】:Generate metadata for parquet files为 parquet 文件生成元数据
【发布时间】:2016-09-16 14:15:00
【问题描述】:

我有一个构建在大量外部 parquet 文件之上的配置单元表。 Parquet 文件应该由 spark 作业生成,但由于将元数据标志设置为 false,它们没有生成。我想知道是否有可能以某种无痛的方式恢复它。文件结构如下:

/apps/hive/warehouse/test_db.db/test_table/_SUCCESS
/apps/hive/warehouse/test_db.db/test_table/_common_metadata
/apps/hive/warehouse/test_db.db/test_table/_metadata
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-20
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-21
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-22
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-23
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-24
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-25
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-26
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-27
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-28
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-29
/apps/hive/warehouse/test_db.db/test_table/end_date=2016-04-30

假设文件_metadata 不存在或已过时。有没有办法通过 hive 命令重新创建它/生成它而无需启动整个 spark 作业?

【问题讨论】:

  • @Niemand 请用您的最新评论编辑问题!
  • _metadata 不会在 .parquet 文件旁边的分区文件夹中吗?另外,你能从 spark shell 中读取文件吗?
  • 是的,一些元数据存在于文件本身中,是的,它们可以从 spark shell 和 hive 查询。只是我认为如果没有这个特定的 _metadata 文件,hive 查询会慢得多。

标签: hadoop apache-spark hive parquet


【解决方案1】:

好的,这就是练习,可以使用 Parquet 工具直接访问元数据。您需要先获取镶木地板文件的页脚:

import scala.collection.JavaConverters.{collectionAsScalaIterableConverter, mapAsScalaMapConverter}

import org.apache.parquet.hadoop.ParquetFileReader
import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.hadoop.conf.Configuration

val conf = spark.sparkContext.hadoopConfiguration

def getFooters(conf: Configuration, path: String) = {
  val fs = FileSystem.get(conf)
  val footers = ParquetFileReader.readAllFootersInParallel(conf, fs.getFileStatus(new Path(path)))
  footers
}

现在您可以按如下方式获取文件元数据:

def getFileMetadata(conf: Configuration, path: String) = {
  getFooters(conf, path)
    .asScala.map(_.getParquetMetadata.getFileMetaData.getKeyValueMetaData.asScala)
}

现在您可以获取 parquet 文件的元数据了:

getFileMetadata(conf, "/tmp/foo").headOption

// Option[scala.collection.mutable.Map[String,String]] =
//   Some(Map(org.apache.spark.sql.parquet.row.metadata ->
//     {"type":"struct","fields":[{"name":"id","type":"long","nullable":false,"metadata":{"foo":"bar"}}
//     {"name":"txt","type":"string","nullable":true,"metadata":{}}]}))

我们还可以在需要时使用提取的页脚编写独立的元数据文件:

import org.apache.parquet.hadoop.ParquetFileWriter

def createMetadata(conf: Configuration, path: String) = {
  val footers = getFooters(conf, path)
  ParquetFileWriter.writeMetadataFile(conf, new Path(path), footers)
}

我希望这能回答您的问题。您可以在awesome-sparkspark-gotchas repo 上阅读有关 Spark 数据帧和元数据的更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    • 2022-10-23
    • 1970-01-01
    • 2017-12-17
    • 1970-01-01
    • 2016-01-01
    • 2018-04-22
    相关资源
    最近更新 更多