Spark从入门到精通8 -- Spark SQL

Spark SQL

Spark SQL简介

  • Spark SQL是用来操作结构化数据的程序包,支持多种数据源(Hive表、Parquet、JSON),可以基于Spark SQL进行数据的查询,为数据计算提供数据入口。
  • Spark SQL提供一种特殊的RDD,叫做DataFrameDataFrame是存放Row对象的RDD,每一个Row对象代表一行记录。

Spark SQL使用

Spark SQL连接
  • maven约束
<dependency>
    <groupId>org.apache.sparkgroupId>
    <artifactId>spark-sql_2.11artifactId>
    <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

你可能感兴趣的:(大数据)