SparkSQL:Parquet数据源之合并元数据

合并元数据

如同ProtocolBuffer,Avro,Thrift一样,Parquet也是支持元数据合并的。用户可以在一开始就定义一个简单的元数据,然后随着业务需要,逐渐往元数据中添加更多的列。在这种情况下,用户可能会创建多个Parquet文件,有着多个不同的但是却互相兼容的元数据。Parquet数据源支持自动推断出这种情况,并且进行多个Parquet文件的元数据的合并。

因为元数据合并是一种相对耗时的操作,而且在大多数情况下不是一种必要的特性,从Spark 1.5.0版本开始,默认是关闭Parquet文件的自动合并元数据的特性的。可以通过以下两种方式开启Parquet数据源的自动合并元数据的特性:

1、读取Parquet文件时,将数据源的选项,mergeSchema,设置为true

2、使用SQLContext.setConf()方法,将spark.sql.parquet.mergeSchema参数设置为true

案例:合并学生的基本信息,和成绩信息的元数据

代码实例

Scala版本:

package com.etc
import org.apache.spark.sql.{SQLContext, SaveMode}
import org.apache.spark.{SparkConf, SparkContext}

/**
  * author: fengze
  * description:
  * Parquet数据源之合并元数据
  */
object ParquetMergeSchema {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
      .setAppName("ParquetMergeSchema")
      .setMaster("local")
    val sc = new SparkContext(conf)
    val sqlContext = new SQLContext(sc)

    import sqlContext.implicits._

    //不用提前创建parquet文件
    // 创建一个DataFrame,作为学生的基本信息,并写入一个parquet文件中
    val studentsWithNameAge = Array(("leo", 23), ("jack", 25)).toSeq
    val studentsWithNameAgeDF = sc.parallelize(studentsWithNameAge, 2).toDF("name", "age")
    studentsWithNameAgeDF.save("F:\\Spark-SQL\\students.parquet", "parquet", SaveMode.Append)

    // 创建第二个DataFrame,作为学生的成绩信息,并写入一个parquet文件中
    val studentsWithNameGrade = Array(("marry", "A"), ("tom", "B")).toSeq
    val studentsWithNameGradeDF = sc.parallelize(studentsWithNameGrade, 2).toDF("name", "grade")
    studentsWithNameGradeDF.save("F:\\Spark-SQL\\students.parquet", "parquet", SaveMode.Append)

    // 首先,第一个DataFrame和第二个DataFrame的元数据肯定是不一样的吧
    // 一个是包含了name和age两个列,一个是包含了name和grade两个列
    // 所以, 这里期望的是,读取出来的表数据,自动合并两个文件的元数据,出现三个列,name、age、grade

    // 用mergeSchema的方式,读取students表中的数据,进行元数据的合并
    //重点:sqlContext.read.option("mergeSchema", "true")
    val students = sqlContext.read.option("mergeSchema", "true")
      .parquet("F:\\Spark-SQL\\students.parquet")

    //打印元数据结构信息
    students.printSchema()

    students.show()
  }
}

复制代码

java版本:

package com.etc;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.SaveMode;

import java.sql.Array;

/**
 * @author: fengze
 * @description:
 * Parquet数据源之合并元数据
 */
public class ParquetMergeSchemaJava {
    public static void main(String[] args) {
      SparkConf conf = new SparkConf()
              .setAppName("ParquetMergeSchemaJava")
              .setMaster("local");
      JavaSparkContext sc = new JavaSparkContext(conf);
      SQLContext sqlContext = new SQLContext(sc);

      //创建第一个studentInfo1基本信息,写入一个parquet文件中
      DataFrame studentInfo1 = sqlContext.read().format("json").load("F:\\studentInfo1.json");
      studentInfo1.write().mode(SaveMode.Append).save("F:\\studentInfo.parquet");

      //创建第两个studentInfo1基本信息,写入一个parquet文件中
      DataFrame studentInfo2 = sqlContext.read().format("json").load("F:\\studentInfo2.json");
      studentInfo2.write().mode(SaveMode.Append).save("F:\\studentInfo.parquet");

      //开启Parquet数据源的自动合并元数据的特性
      //重点:sqlContext.read.option("mergeSchema", "true")
      DataFrame studentInfo = sqlContext.read().option("mergeSchema", "true")
              .parquet("F:\\studentInfo.parquet");

      //打印元数据结构信息
      studentInfo.printSchema();

      studentInfo.show();
    }
}

复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值