4.3Spark SQL数据源-Parquet文件

一、Parquet概述


Apache Parquet是Hadoop生态系统中任何项目都可以使用的列式存储格式,不受数据处理框架、数据模型和编程语言的影响。Spark SQL支持对Parquet文件的读写,并且可以自动保存源数据的Schema。当写入Parquet文件时,为了提高兼容性,所有列都会自动转换为“可为空”状态。

二、读取和写入Parquet的方法


加载和写入Parquet文件时,除了可以使用load()方法和save()方法外,还可以直接使用Spark SQL内置的parquet()方法

(一)利用parquet()方法读取parquet文件
1、读取parquet文件
执行命令:val usersdf = spark.read.parquet("hdfs://master:9000/input/users.parquet")

2、显示数据帧内容
执行命令:usersdf.show()

(二)利用parquet()方法写入parquet文件
1、写入parquet文件
执行命令:usersdf.select("name", "favorite_color").write.parquet("hdfs://master:9000/result")

报错说/result目录已经存在,有两种解决问题的方式,一个是删除result目录,一个是修改命令,设置覆盖模式
导入SaveMode类后,执行命令:usersdf.select("name", "favorite_color").write.mode(SaveMode.Overwrite)parquet("hdfs://master:9000/result")

2、查看生成的parquet文件
在slave1虚拟机上执行命令:hdfs dfs -ls /result

三、Schema合并


(一)Schema合并概述
与Protocol Buffer、Avro和Thrift一样,Parquet也支持Schema合并。刚开始可以先定义一个简单的Schema,然后根据业务需要逐步向Schema中添加更多的列,最终会产生多个Parquet文件,各个Parquet文件的Schema不同,但是相互兼容。对于这种情况,Spark SQL读取Parquet数据源时可以自动检测并合并所有Parquet文件的Schema。
(二)开启Schema合并功能
由于Schema合并是一个相对耗时的操作,并且在多数情况下不是必需的,因此从Spark 1.5.0开始默认将Schema自动合并功能关闭,可以通过两种方式开启。
1、利用option()方法设置
读取Parquet文件时,通过调用option()方法将数据源的属性mergeSchema设置为true
val mergedDF = spark.read.option("mergeSchema", "true").parquet("hdfs://master:9000/students")
1
2、利用config()方法设置
构建SparkSession对象时,通过调用config()方法将全局SQL属性spark.sql.parquet.mergeSchema设置为true
val spark = SparkSession.builder()
  .appName("SparkSQLDataSource")
  .config("spark.sql.parquet.mergeSchema", true)
  .master("local[*]")  
  .getOrCreate()
1
2
3
4
5
(三)案例演示Schema合并
1、提出任务
向HDFS的目录/students中首先写入两个学生的姓名和年龄信息,然后写入两个学生的姓名和成绩信息,最后读取/students目录中的所有学生数据并合并Schema。
2、完成任务
创建SchemaMergeDemo单例对象

package net.hw.sparksql

import org.apache.spark.sql.{SaveMode, SparkSession}

/**
 * 功能:演示Schema合并
 * 作者:华卫
 * 日期:2022年05月11日
 */
object SchemaMergeDemo {
  def main(args: Array[String]): Unit = {   
    // 创建或得到SparkSession
    val spark = SparkSession.builder()
      .appName("SparkSQLDataSource")
      .config("spark.sql.parquet.mergeSchema", true)
      .master("local[*]")
      .getOrCreate()

    // 导入隐式转换
    import spark.implicits._

    // 创建列表集合,存储姓名和年龄
    val studentList1 = List(("李克文", 23), ("张晓琳", 28))
    // 将列表集合转为数据帧,并指定列名name和age
    val studentDF1 = spark.sparkContext
      .makeRDD(studentList1)
      .toDF("name", "age")
    // 输出数据帧内容
    studentDF1.show()
    // 将数据帧写入HDFS指定目录
    studentDF1.write.mode(SaveMode.Append)
      .parquet("hdfs://master:9000/students")

    // 创建列表集合,存储姓名和成绩
    val studentList2 = List(("无心剑", 99), ("陈鸿宇", 78))
    // 将列表集合转为数据帧,并指定列名name和age
    val studentDF2 = spark.sparkContext
      .makeRDD(studentList2)
      .toDF("name", "score")
    // 输出数据帧内容
    studentDF2.show()
    // 将数据帧写入HDFS指定目录
    studentDF2.write.mode(SaveMode.Append)
      .parquet("hdfs://master:9000/students")

    // 读取指定目录下多个文件
    val mergedDF = spark.read.option("mergeSchema", true)
      .parquet("hdfs://master:9000/students")
    // 输出Schema信息
    mergedDF.printSchema()
    // 输出数据帧内容
    mergedDF.show()
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
运行程序,抛出两个异常
第一个是IO异常:java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.

第二个是访问控制异常:org.apache.hadoop.security.AccessControlException: Permission denied: user=Administrator, access=WRITE, inode="/students":root:supergroup:drwxr-xr-x

先解决第一个异常。在Windows环境中缺少winutils.exe程序而抛出异常。一般情况下,Spark运行在Linux系统上,在Windows下运行时需要安装支持插件hadoop2.7-common-bin
下载链接:https://pan.baidu.com/s/1TbmAnwi4hscLtlqV9-rrXg 提取码:plis

解压缩到指定目录

设置环境变量,让系统可以搜索到winutils.exe

解决第二个异常。添上一句,设置HADOOP用户名属性

创建日志属性文件 - log4j.properties,免得看见太多Spark的log信息

log4j.rootLogger=stdout, logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spark.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
1
2
3
4
5
6
7
8
运行程序,查看结果

从输出的Schema信息和数据内容可以看出,Spark SQL在读取Parquet文件数据时,自动将不同文件的Schema信息进行合并
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spark SQL可以通过DataFrame API或SQL语句来操作外部数据源,包括parquet、hive和mysql等。其中,parquet是一种列式存储格式,可以高效地存储和查询大规模数据;hive是一种基于Hadoop的数据仓库,可以通过Spark SQL来查询和分析;而mysql是一种常见的关系型数据库,可以通过Spark SQL来读取和写入数据。在使用Spark SQL操作外部数据源时,需要先创建DataFrame或注册表,然后通过API或SQL语句来进行数据的读取、过滤、聚合等操作。同时,还可以通过Spark SQL的连接器来实现不同数据源之间的数据传输和转换。 ### 回答2: Spark SQL 是 Apache Spark 中的一个模块,用于在大规模数据集上进行结构化数据处理。它支持多种数据源,并提供了访问、查询和操作这些数据源的功能。 对于外部数据源的操作,Spark SQL 提供了适配器和驱动程序来连接不同的数据源。下面简单介绍一下对于三种常见的数据源Parquet、Hive、MySQL)的操作方式: 1. ParquetParquet 是一种列式存储格式,适用于大规模数据存储和分析。对于 Parquet 数据源Spark SQL 提供了原生的支持,你可以直接使用 `spark.read.parquet()` 方法读取 Parquet 文件,并通过 `write.parquet()` 方法写入 Parquet 文件Spark SQL 会自动推断 Parquet 文件的模式(schema),你也可以通过指定模式参数来指定具体的模式。 2. Hive:Hive 是一个数据仓库基础设施,可以在 Hadoop 上进行数据仓库的处理和查询。Spark SQL 可以与 Hive 结合使用,使用 Hive 提供的 metastore 来管理表和模式,通过 HiveQL(Hive 查询语言)来查询和操作 Hive 数据。你可以通过 `spark.sql()` 方法来执行 HiveQL 查询,也可以使用 `registerTempTable()` 方法将一个 Spark DataFrame 注册为一个临时表,然后通过 SQL 语句查询这个临时表。 3. MySQL:MySQL 是一种关系型数据库管理系统,Spark SQL 也可以与 MySQL 进行集成。首先,需要在 Spark 中导入相应的 MySQL 驱动程序,例如 "com.mysql.jdbc.Driver"。然后,通过 `spark.read.format("jdbc")` 方法来读取 MySQL 数据库中的表,你需要指定连接 URL、表名、用户名和密码等参数。使用相同的方式,你也可以将 Spark DataFrame 写入到 MySQL 数据库中。 总结起来,Spark SQL 对于 Parquet、Hive 和 MySQL 这些外部数据源都提供了直接的支持和集成。通过适配器和驱动程序,你可以使用 Spark SQL 的 API 和功能来读取、写入、查询和操作这些外部数据源中的数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值