Spark 2.2.1 Parquet文件处理的案例与解读

Spark 2.2.1 Parquet文件处理的案例与解读 

(一) 加载数据

加载Parquet数据源,并将加载后的people使用createOrReplaceTempView方法注册到临时表中,然后使用SQL语句对该临时表进行操作,最后将操作结果打印出来。

scala> valpeople =spark.read.parquet("/resources/people.parquet")

18/02/18 08:51:40WARN metastore.ObjectStore: Failed to get database global_temp, returningNoSuchObjectException

people:org.apache.spark.sql.DataFrame = [age: bigint, name: string]

 

scala>people.createOrReplaceTempView("parquetFile")

 

scala> valteenagers = spark.sql("SELECT name FROM parquetFile WHERE age >= 13 ANDage <= 19")

teenagers:org.apache.spark.sql.DataFrame = [name: string]

 

scala>teenagers.show

+------+

|  name|

+------+

|Justin|

+------+

 

(二) 分区发现

在类似于Hive的系统上,表分区是一种常见的优化方法。在一个分区表中,数据通常存储在不同的目录中,将分区列值编码到每个分区目录的路径上。Parquet数据源可以自动地发现和推导分区信息。

例如,我们可以带上额外的列gender,作为我们的分区列,用以下目录结构,将员工信息数据存储到分区表中:

path

└── to

    └── table

        ├── gender=male

        │   └── data.parquet

        └── gender=female

         │  └── data.parquet

        │   └── ...

 

通过将分区表的路径传递到spark.read.parquet或spark.read.load,Spark SQL会自动地从路径中提取分区信息。返回的DataFrame/DataSet将构建Schema。

root

|-- name: string(nullable = true)

|-- age: long(nullable = true)

|-- gender: string(nullable = true)

|-- salary: string(nullable = true)

 

         注意,用于分区的列的数据类型是自动推导的,自动推导支持数字数据类型和字符串类型。

分区发现案例参考以下“合并Schema”的案例。

(三) 合并Schema。

和ProtocolBuffer, Avro 和 Thrift 一样,Parquet也支持Schema演变,用户可以先使用一个简单的Schema,然后根据需要逐步添加更多的列到Schema中。通过这种方式,最终可以让多个不同的Parquet在Schema上互相兼容。Parquet数据源目前可以自动检测到这种情况,并合并所有这些文件。

以下案例说明合并Schema的详细步骤:

1)       构建一个元素值为(i,i * i)的RDD,并转化为列名为("value","square")的DataFrame,获取从1到5的每个元素的平方值。

scala>  val squaresDF = spark.sparkContext.makeRDD(1to 5).map(i => (i, i * i)).toDF("value",

 "square")

squaresDF:org.apache.spark.sql.DataFrame = [value: int, square: int]     

 

2)       将构建的squaresDF存储到test_table的key=1子目录下。

scala>  squaresDF.write.parquet("/data/test_table/key=1")       

 

3)       构建一个元素值为(i,i * i* i)的RDD,并转化为列名为("value", "cube")的DataFrame,获取从6到10的每个元素的立方值。

scala>    val cubesDF = spark.sparkContext.makeRDD(6to 10).map(i => (i, i * i * i)).toDF("value",

"cube")

cubesDF:org.apache.spark.sql.DataFrame = [value: int, cube: int]       

 

4)       将构建的cubesDF存储到test_table的key=2子目录下。

scala> cubesDF.write.parquet("/data/test_table/key=2")      

 

5)       通过数据源选项option("mergeSchema","true")启用模式合并,读取包含两个子目录的test_table目录,自动推导出对应的Parquet数据源的Schema信息。

scala> valmergedDF = spark.read.option("mergeSchema","true").parquet("/data/test_table")

mergedDF:org.apache.spark.sql.DataFrame = [value: int, square: int ... 2 more fields]      

 

6)        打印mergedDF的Schema信息。

scala>mergedDF.printSchema()

root

 |-- value: integer (nullable = true)

 |-- square: integer (nullable = true)

 |-- cube: integer (nullable = true)

 |-- key: integer (nullable = true)    

 

7)       查询squaresDF的数据。

scala>squaresDF.show

+-----+------+

|value|square|

+-----+------+

|    1|    1|

|    2|    4|

|    3|    9|

|    4|   16|

|    5|   25|

+-----+------+

 

8)       查询cubesDF的数据。

scala>cubesDF.show

+-----+----+

|value|cube|

+-----+----+

|    6| 216|

|    7| 343|

|    8| 512|

|    9| 729|

|   10|1000|

+-----+----+    

 

9)       查询mergedDF的数据。

scala>mergedDF.show

+-----+------+----+---+

|value|square|cube|key|

+-----+------+----+---+

|    1|    1|null|  1|

|    2|    4|null|  1|

|    3|    9|null|  1|

|    4|   16|null|  1|

|    5|   25|null|  1|

|    6| null| 216|  2|

|    7| null| 343|  2|

|    8| null| 512|  2|

|    9| null| 729|  2|

|   10| null|1000|  2|

+-----+------+----+---+    

 

Parquet数据分区保存后的Web Interface界面(http://192.168.189.1:50070/explorer.html#/data/test_table),如图3-5所示。

Spark 2.2.1 Parquet文件处理的案例与解读_第1张图片

图 3 - 5 Parquet数据分区保存

合并Schema案例,首先通过spark.sparkContext.makeRDD方法构建一个RDD实例,然后调用RDD实例的toDF方法指定Schema,生成DataFrame实例,对应的Schema信息为:[value:int, square: int]。然后将该DataFrame实例squaresDF,保存到分区路径"/data/test_table/key=1"下。

用相同的方法构建DataFrame实例cubesDF,对应的Schema为[value: int, cube: int],cubesDF的Schema信息比squaresDF添加列”cube”列,同时删除了” square”列,然后保存到分区路径"/data/test_table/key=2"下。

最后读取分区表到Parquet,其路径为包含"/data/test_table/key=1"和"/data/test_table/key=2"两个路径的"/data/test_table"路径,加载构建DataFrame实例mergedDF之后,会自动推导出mergedDF的Schema信息,最终推导出的Schema信息为[value: int, square:int ... 2 more fields],包含列squaresDF和cubesDF的 ”value”,”square”和” cube”列信息,以及出现在分区路径上的 ”key”分区列信息。

注意:如果没有指定具体路径,在使用HDFS作为存储系统时,默认会放在HDFS文件系统中当前用户/user/root的目录下,例如” /user/root/data/test_table/”目录;如果指定具体路径,在指定的路径目录下“/data/test_table”,可以看到文件已经保存成功。

如果目录以/开头,则对应的是HDFS的根目录(对应core-site.xml中的fs.defaultFS配置属性),而非当前用户所在目录下。例如/data,对应为hdfs://namenode:port/data。其中namenode为启动NameNode进程的节点,当前环境下的节点地址为http://192.168.189.1。



2018年新春报喜!热烈祝贺王家林大咖大数据经典传奇著作《SPARK大数据商业实战三部曲》畅销书籍 清华大学出版社发行上市!

本书基于Spark 2.2.0最新版本(2017年7月11日发布),以Spark商业案例实战和Spark在生产环境下几乎所有类型的性能调优为核心,以Spark内核解密为基石,分为上篇、中篇、下篇,对企业生产环境下的Spark商业案例与性能调优抽丝剥茧地进行剖析。上篇基于Spark源码,从一个动手实战案例入手,循序渐进地全面解析了Spark 2.2新特性及Spark内核源码;中篇选取Spark开发中最具有代表的经典学习案例,深入浅出地介绍,在案例中综合应用Spark的大数据技术;下篇性能调优内容基本完全覆盖了Spark在生产环境下的所有调优技术。


本书适合所有Spark学习者和从业人员使用。对于有分布式计算框架应用经验的人员,本书也可以作为Spark高手修炼的参考书籍。同时,本书也特别适合作为高等院校的大数据教材使用。

当当网、京东、淘宝、亚马逊等网店已可购买!欢迎大家购买学习!

当当网址:  http://product.dangdang.com/25230552.html

你可能感兴趣的:(AI,&,Big,Data案例实战课程)