大数据开发:Spark SQL数据读取

Spark框架当中,对于Spark SQL而言,进行数据处理的前提是先要引入数据,读取到数据,才能进行接下来的数据处理环节。今天的大数据开发分享,我们就来讲讲Spark SQL数据读取这个环节,也会给到相应的一些示例。

Spark SQL数据读取

1、parquet

1)读取Parquet文件

parquet文件自带schema,读取后是DataFrame格式。

val usersDF =spark.read.load("examples/src/main/resources/users.parquet")

//usersDF: org.apache.spark.sql.DataFrame = [name:string, favorite_color: string ... 1 more field]

2)解析分区信息

parquet文件中如果带有分区信息,那么SparkSQL会自动解析分区信息。比如,这样一份人口数据按照gender和country进行分区存储,目录结构如下:

test

└── spark-sql

    └── test

        ├──gender=male

       │   │

       │   ├── country=US

       │   │   └── data.parquet

       │   ├── country=CN

       │   │   └── data.parquet

       │   └── ...

        └──gender=female

            │

           ├── country=US

           │   └── data.parquet

           ├── country=CN

           │   └── data.parquet

           └── ...

通过spark.read.load读取该目录下的文件SparkSQL将自动解析分区信息,返回的DataFrame的Schema如下:

root

|-- name: string (nullable = true)

|-- age: long (nullable = true)

|-- gender: string (nullable = true)

|-- country: string (nullable = true)

目前自动解析分区支持数值类型和字符串类型。

自动解析分区类型的参数为:spark.sql.sources.partitionColumnTypeInference.enabled,默认值为true。可以关闭该功能,直接将该参数设置为disabled。此时,分区列数据格式将被默认设置为string类型,不会再进行类型解析。

3)Schema合并

如果读取的多个parquet文件中的Schema信息不一致,Spark SQL可以设置参数进行合并,但是Schema合并是一个高消耗的操作,在大多数情况下并不需要,所以Spark SQL从1.5.0开始默认关闭了该功能。

可以通过下面两种方式开启该功能:

a.读取文件的时候,开启合并功能,只对本次读取文件进行合并Schema操作

b.设置全局SQL选项spark.sql.parquet.mergeSchema为true,每次读取文件都会进行合并Schema操作

具体示例:

// sqlContext是之前例子中生成的

// 导入隐式转换

import sqlContext.implicits._

// 创建一个简单的DataFrame并保存

val df1 = sc.makeRDD(1 to 5).map(i => (i, i *2)).toDF("single", "double")

df1.write.parquet("data/test_table/key=1")

// 创建另一个DataFrame,注意字段名

val df2 = sc.makeRDD(6 to 10).map(i => (i, i *3)).toDF("single", "triple")

df2.write.parquet("data/test_table/key=2")

// 读取这两个parquet文件,增加开启合并Schema的设置

val df3 =sqlContext.read.option("mergeSchema","true").parquet("data/test_table")

df3.printSchema()

// 不同名称的字段都保留下来了

// root

// |-- single: int (nullable = true)

// |-- double: int (nullable = true)

// |-- triple: int (nullable = true)

// |-- key : int (nullable = true)

关于schema合并,有一点需要特别关注,那就是当不同parquet文件的schema有冲突时,合并会失败,如同名的字段,其类型不一致的情况。这时如果你读取的是hive数据源,可能会出现读取失败或者读取字段值全部为NULL的情况。如果大家遇到类型场景,可以考虑是否是这个因素导致。

2、json

json文件和parquet文件一样也是带有schema信息,不过需要指明是json文件,才能准确的读取。

val peopleDF =spark.read.format("json").load("examples/src/main/resources/people.json")

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

3、MySQL

读取MySQL中的数据是通过jdbc的方式,需要知道要访问的MySQL数据库、表等信息,具体请看下面的代码:

//MySQL数据的访问ip、端口号和数据库名

val url ="jdbc:mysql://192.168.100.101:3306/testdb"

//要访问的表名

val table = "test"

//建立一个配置变量

val properties = new Properties()

//将用户名存入配置变量

properties.setProperty("user","root")

//将密码存入配置变量

properties.setProperty("password","root")

//需要传入Mysql的URL、表名、配置变量

val df = sqlContext.read.jdbc(url,table,properties)

这里要注意的一个点是,读取MySQL需要运行作业时,classpath下有MySQL的驱动jar,或者通过--jars添加驱动jar。

4、hive

读取hive数据的前提是要进行相关的配置,需要将hive-site.xml、core-site.xml、hdfs-site.xml以及hive的lib依赖放入spark的classpath下,或者在提交作业时通过--files和--jars来指定这些配置文件和jar包。之后,就可以很方便的使用hive的数据表了,示例代码如下:

import java.io.File

import org.apache.spark.sql.Row

import org.apache.spark.sql.SparkSession

case class Record(key: Int, value: String)

// 数仓地址指向默认设置

val warehouseLocation = newFile("spark-warehouse").getAbsolutePath

val spark = SparkSession

  .builder()

.appName("Spark Hive Example")

.config("spark.sql.warehouse.dir", warehouseLocation)

.enableHiveSupport() //增加支持hive特性

.getOrCreate()

import spark.implicits._

import spark.sql

//使用sql创建一个表,并将hdfs中的文件导入到表中

sql("CREATE TABLE IF NOT EXISTS src (key INT,value STRING) USING hive")

sql("LOAD DATA LOCAL INPATH 'examples/src/main/resources/kv1.txt' INTO TABLE src")

// 使用sql直接指向sql查询

sql("SELECT * FROM src").show()

// +---+-------+

// |key| value|

// +---+-------+

// |238|val_238|

// | 86| val_86|

// |311|val_311|

// ...

关于大数据开发,Spark SQL数据读取,以上就为大家做了简单的介绍了。Spark SQL数据读取,往往需要看引入数据源的格式问题,根据不同的格式选择相应的方式去处理就行了。

你可能感兴趣的:(大数据开发:Spark SQL数据读取)