Spark SQL
Spark SQL
简介
Spark SQL
是用来操作结构化数据的程序包,支持多种数据源(Hive表、Parquet、JSON)
,可以基于Spark SQL
进行数据的查询,为数据计算提供数据入口。Spark SQL
提供一种特殊的RDD
,叫做DataFrame
,DataFrame
是存放Row
对象的RDD
,每一个Row
对象代表一行记录。
Spark SQL
使用
Spark SQL
连接
maven
约束
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>${spark-version}</version>
</dependency>
- 代码
demo
val spark: SparkSession = SparkSession.builder().config(conf = sparkConf).getOrCreate()
Spark SQL
读取和存储数据
- 读取
json
格式文件
object SparkSQLDemo {
val conf = new SparkConf().setAppName("Spark SQL demo").setMaster("local")
val spark = SparkSession.builder().config(conf).getOrCreate()
def main(args: Array[String]): Unit = {
val jsonData = spark.read.json("test.json")
/*
显示jsonData的DataFrame表数据
+---+----+
|age|name|
+---+----+
| 24| pfd|
| 25| lsh|
| 25| yhy|
| 25| cfx|
| 25| xjq|
| 23| zy|
| 24| blx|
+---+----+
*/
jsonData.show()
//将jsonData设置为临时表
jsonData.createOrReplaceTempView("user")
//sql查询 返回一个DataFrame
val ageData = spark.sql("select sum(age) from user")
//打印当前临时表是否被缓存到内存中
println(spark.catalog.isCached("user")) //false
//将user临时表缓存到内存中
println(spark.catalog.cacheTable("user"))
println(spark.catalog.isCached("user")) //ture
//获取当前数据库中的tables
val tables = spark.catalog.listTables()
//获取当前sparkSession中的databases
val databases = spark.catalog.listDatabases()
/**
遍历打印
database.toString():
Database[name='default', description='default database', path='file:/workspace/spark-warehouse']
*/
databases.foreach(database => {
println("database.toString(): " + database.toString())
})
/**
table.toString(): Table[name='user', tableType='TEMPORARY', isTemporary='true']
*/
tables.foreach(table => {
println("table.toString(): " + table.toString())
})
/**
+------------------------+
|sum(CAST(age AS DOUBLE))|
+------------------------+
| 171.0|
+------------------------+
*/
ageData.show()
/**
打印表结构
root
|-- sum(CAST(age AS DOUBLE)): double (nullable = true)
*/
ageData.printSchema()
/**
age sum: 171.0
*/
ageData.foreach(row => {
println("age sum: " + row.getDouble(0))
})
/**
row.getString(1): pfd
row.getString(1): lsh
row.getString(1): yhy
row.getString(1): cfx
row.getString(1): xjq
row.getString(1): zy
row.getString(1): blx
*/
jsonData.foreach(row => {
println("row.getString(1): " + row.getString(1))
})
}
}
这里catalog
对象是SparkSession
的元数据,存储了数据库集合信息。通过它能访问SparkSession
在运行中创建的数据库,表,数据等所有信息。
RDD
转换为DataFrame
本质就是将RDD[Any]
转换成RDD[ROW]
//将RDD[String]转化为RDD[Array[String]]
val rdd: RDD[Array[String]]= rdd.map(record=>{
val line = new JSONObject(record)
Array(line.getString("a"),line.getString("b"),line.getString("c"),line.getString("d"));
})
//将RDD[Array[String]]转换为RDD[ROW]
val rowRDD: RDD[Row] = rdd.map(x => Row(x(0),x(1).toInt,x(2),x(3)))
//设置列信息
val schema: StructType = (new StructType)
.add("a", StringType)
.add("b",IntegerType)
.add("c",StringType)
.add("d",StringType)
//创建DataFrame
val linesDf = spark.createDataFrame(rowRDD,schema)
Spark SQL UDF
自定义函数
- 代码
demo
/**
定义函数 获取String类型字符串长度
*/
def nameLength(name: String): Int = {
if(name!= null && name.length > 0) {
return name.length
} else {
return -1
}
}
/**
将函数注册到SparkSession中
*/
spark.udf.register("nameLength",nameLength(_:String))
/**
调用自定义函数进行查询
+---------+
|UDF(name)|
+---------+
| 3|
| 3|
| 3|
| 3|
| 3|
| 2|
| 3|
+---------+
*/
spark.sql("select nameLength(name) from user").show()
Spark SQL
性能
- 优化策略
1、SparkSQL
查询操作可以下移到查询引擎上,如果我们只是需要某个数据集中的部分列数据,我们可以在加载的时候只加载需要的列,而不是全量加载后,基于内存进行筛选。
2、conf
参数
选项 | 默认值 | 用途 |
---|---|---|
spark.sql.codegen | false | 每条查询语句编译成Java 二进制代码,大型查询提高性能 |
spark.sql.inMemoryColumnarStorage.commpressed | false | 内存中列式存储压缩 |
spark.sql.imMemoryColumnarStorage.batchSize | 1000 | 列式存储时批处理大小,过大OOM |
spark.sql.parquet.compression.codec | snappy | 压缩格式gzip/lzo/uncompression |