为 parquet 文件生成元数据
Generate metadata for parquet files
我有一个配置单元 table,它构建在大量外部镶木地板文件之上。 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 command/generate 重新创建它而不必启动整个 spark 作业?
好的,下面是练习,可以使用 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-spark's spark-gotchas repo.
上阅读有关 Spark DataFrames 和元数据的更多信息
我有一个配置单元 table,它构建在大量外部镶木地板文件之上。 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 command/generate 重新创建它而不必启动整个 spark 作业?
好的,下面是练习,可以使用 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-spark's spark-gotchas repo.
上阅读有关 Spark DataFrames 和元数据的更多信息