SparkSQL(5)——Spark SQL编程方式执行查询

本文详细介绍如何在Spark中将RDD转换为DataFrame,包括通过反射机制和StructType指定Schema的方法,以及如何使用SparkSession操作HiveContext进行数据处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编写Spark SQL程序实现RDD转换成DataFrame

Spark官网提供了两种方法来实现从RDD转换得到DataFrame,第一种方法是利用反射机制,推导包含某种类型的RDD,通过反射将其转换为指定类型的DataFrame,适用于提前知道RDD的schema。第二种方法通过编程接口与RDD进行交互获取schema,并动态创建DataFrame,在运行时决定列及其类型。
一、添加maven依赖

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-sql_2.11</artifactId>
    <version>2.1.3</version>
</dependency>
通过反射推断Schema

Scala支持使用case class类型导入RDD转换为DataFrame,通过case class创建schema,case class的参数名称会被利用反射机制作为列名。这种RDD可以高效的转换为DataFrame并注册为表。
package com.fgm.sparksql

import org.apache.spark.sql.SparkSession

//利用反射,将rdd转换成dataFrame
case class Person(val id:Int,val name:String,val age:Int)


object SchemaDemo {
  def main(args: Array[String]): Unit = {

    //创建SparkSession对象
    val sparkSession = SparkSession.builder().appName("Schema").master("local[2]").getOrCreate()
    //创建SparkContext对象
    val sc = sparkSession.sparkContext
    sc.setLogLevel("WARN")
    //读取数据文件
    val rdd1 = sc.textFile("D:\\tmp\\person.txt").map(_.split(" "))
    //将rdd与样例类关联
    val personRDD = rdd1.map(x=>Person(x(0).toInt,x(1),x(2).toInt))
    //将personRDD转换成DataFrame,需导入隐式转换
    import sparkSession.implicits._
    val personDF = personRDD.toDF()
    //dataFrame操作
    //DSL风格
    personDF.printSchema()
    personDF.show()
    personDF.select("name","age").show()
    personDF.select($"age">30).show()

    //sql风格语法
    personDF.createTempView("person")
    sparkSession.sql("select * from person").show()
    sparkSession.sql("select * from person where age>30").show()
    sparkSession.sql("select * from person where id=3").show()


    sparkSession.stop()
  }
}
通过StructType直接指定Schema

当case class不能提前定义好时,可以通过以下三步创建DataFrame
(1)将RDD转为包含Row对象的RDD
(2)基于StructType类型创建schema,与第一步创建的RDD相匹配
(3)通过sparkSession的createDataFrame方法对第一步的RDD应用schema创建DataFrame

package com.fgm.sparksql

import org.apache.spark.sql.types.{IntegerType, StringType, StructField, StructType}
import org.apache.spark.sql.{Row, SparkSession}

/**
  *通过StructType指定schema,将rdd转换成dataFrame
  * @Auther: fgm
  */
object StructTypeSchema {
  def main(args: Array[String]): Unit = {
    //创建SparkSession对象
    val spark = SparkSession.builder().appName("StructTypSchema").master("local[2]").getOrCreate()
    //创建SparkContext
    val sc = spark.sparkContext
    sc.setLogLevel("WARN")
    //读取数据
    val rdd1 = sc.textFile("D:\\tmp\\person.txt").map(_.split(" "))
    //将rdd与rowd对象关联
    val rowRDD = rdd1.map(x=>Row(x(0).toInt,x(1),x(2).toInt))

    //指定schema
    val schema=(new StructType).add(StructField("id",IntegerType,true))
      .add(StructField("name",StringType,false))
      .add(StructField("age",IntegerType,true))

    val dataFrame = spark.createDataFrame(rowRDD,schema)
    dataFrame.printSchema()
    dataFrame.show()

    dataFrame.createTempView("person")
    spark.sql("select * from person").show()

    spark.stop()
  }
}

编写程序操作HiveContext

HiveContext是对应spark-hive这个项目,与hive有部分耦合, 支持hql,是SqlContext的子类,在Spark2.0之后,HiveContext和SqlContext在SparkSession进行了统一,可以通过操作SparkSession来操作HiveContext和SqlContext。

添加依赖
<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-hive_2.11</artifactId>
    <version>2.1.3</version>
</dependency>
实现
package com.fgm.sparksql

import org.apache.spark.sql.SparkSession

/**
  *SparkSql操作
  *
  * @Auther: fgm
  */
object HiveSparkSql {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder().appName("HiveSparkSql").master("local[2]").enableHiveSupport().getOrCreate()
    spark.sql("create table user(id int,name string,age int) row format delimited fields terminated by ','")
    spark.sql("load data local inpath './data/user.txt' into table user")
    spark.sql("select * from user").show()

    spark.stop()
  }

}

注意:这里首先在项目根目录下创建data目录(和src同级),然后在data中穿件user.txt文件,并写入相关数据(1,zhangsan,22)。不然会报错。另外需要开启HiveSupport服务:enableHiveSupport()
在这里插入图片描述

### 关于 Spark SQL 的普通样例类编程 以下是基于 Spark SQL 使用普通样例类进行编程的一个完整示例代码,该代码展示了如何通过定义样例类来操作 DataFrame 并完成基本的数据处理任务。 #### 定义样例类 在 Scala 中,可以通过定义样例类 (case class)数据结构。这些样例类会被用于映射输入数据并生成 DataFrame 或 Dataset[^1]。 ```scala // 定义样例类 Person 示人员信息 case class Person(name: String, age: Int) object sparkSQLExample { def main(args: Array[String]): Unit = { // 初始化 SparkSession val spark = org.apache.spark.sql.SparkSession.builder() .appName("SparkSQL Example") .master("local[*]") .getOrCreate() import spark.implicits._ // 创建 RDD 数据集 val peopleRDD = spark.sparkContext.parallelize(Seq( "Alice,25", "Bob,30", "Charlie,35" )) // 将 RDD 转换为 DataFrame 并应用样例类 val personDF = peopleRDD.map(_.split(",")).map(attributes => Person(attributes(0), attributes(1).trim.toInt)).toDF() // 显示 DataFrame 结果 personDF.show() // 注册临时视图以便运行 SQL 查询 personDF.createOrReplaceTempView("people") // 执行 SQL 查询 val resultDF = spark.sql("SELECT name FROM people WHERE age >= 30") // 输出查询结果 resultDF.show() // 停止 SparkSession spark.stop() } } ``` 上述代码实现了以下几个功能: 1. **初始化 SparkSession**:创建了一个名为 `SparkSQL Example` 的 Spark 应用程序实例。 2. **定义样例类**:使用 `case class` 定义了 `Person` 类型,其中包含两个字段——姓名 (`name`) 和年龄 (`age`)。 3. **转换为 DataFrame**:将原始字符串形式的 RDD 数据转化为由样例类组成的 DataFrame。 4. **注册临时视图**:允许后续通过 SQL 查询访问 DataFrame 数据5. **执行 SQL 查询**:筛选出符合条件的结果,并展示最终输出。 此代码片段充分体现了 Spark SQL 对样例类的支持以及其强大的数据分析能力[^4]。 --- ### 实验效果说明 当运行以上代码时,预期会看到如下两部分输出: 1. **初始 DataFrame 展示** ```plaintext +-------+---+ | name|age| +-------+---+ | Alice| 25| | Bob| 30| |Charlie| 35| +-------+---+ ``` 2. **SQL 查询结果** ```plaintext +------+ | names| +------+ | Bob| |Charlie| +------+ ``` 这明成功过滤出了所有满足条件(即年龄大于等于 30)的人名记录[^2]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值