SparkSQL 核心编程

SparkSQL 核心编程

新的起点

Spark Core中,如果想要执行应用程序,需要首先构建上下文环境对象SparkContext,Spark SQL其实可以理解为对Spark Core的一种封装,不仅仅在模型上进行了封装,上下文环境对象也进行了封装。
在老的版本中,SparkSQL提供两种SQL查询起始点:一个叫SQLContext,用于Spark自己提供的SQL查询;一个叫HiveContext,用于连接Hive的查询。

SparkSession是Spark最新的SQL查询起始点,实质上是SQLContext和HiveContext的组合,所以在SQLContex和HiveContext上可用的API在SparkSession上同样是可以使用的。SparkSession内部封装了SparkContext,所以计算实际上是由sparkContext完成的。当我们使用
spark-shell 的时候, spark 会自动的创建一个叫做spark的SparkSession, 就像我们以前可以自动获取到一个sc来表示SparkContext

DataFrame

Spark SQL的DataFrame API 允许我们使用 DataFrame 而不用必须去注册临时表或者生成 SQL 表达式。DataFrame API 既有 transformation操作也有action操作。

创建DataFrame

从Spark数据源进行创建
  • 查看Spark支持创建文件的数据源格式
scala> spark.read.
csv   format   jdbc   json   load   option   options   orc   parquet   schema   table   text   textFile
  • 读取json文件创建DataFrame
scala> val df = spark.read.json("examples/src/main/resources/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]

注意:如果从内存中获取数据,spark可以知道数据类型具体是什么。
如果是数字,默认作为Int处理;但是从文件中读取的数字,不能确定是什么类型,所以用bigint接收,可以和Long类型转换,但是和Int不能进行转换。

  • 展示结果
scala> df.show
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+
从RDD进行转换
从Hive Table进行查询返回

SQL语法

这种风格的查询必须要有临时视图或者全局视图来辅助

  • 读取JSON文件创建DataFrame
scala> val df = spark.read.json("examples/src/main/resources/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]
  • 对DataFrame创建一个临时表
scala> df.createOrReplaceTempView("people")
  • 通过SQL语句实现查询全表
scala> val sqlDF = spark.sql("select * from people")
sqlDF: org.apache.spark.sql.DataFrame = [age: bigint, name: string]
  • 结果展示
scala> sqlDF.show
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+

注意:普通临时表是Session范围内的,如果想应用范围内有效,可以使用全局临时表。
使用全局临时表时需要全路径访问,如global_temp.people

  • 对于DataFrame创建一个全局表
scala> df.createGlobalTempView("people")
  • 通过SQL语句实现查询全表
scala> spark.sql("select * from global_temp.people").show
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+


scala> spark.newSession.sql("select * from global_temp.people").show
+----+-------+
| age|   name|
+----+-------+
|null|Michael|
|  30|   Andy|
|  19| Justin|
+----+-------+

DSL语法

DataFrame提供一个特定领域语言(domain-specific language, DSL)去管理结构化数据。
可以在Scala,Java,Python和R中使用DSL,使用DSL语法风格不必去创建临时视图了。

  • 创建一个DataFrame
scala> val df = spark.read.json("examples/src/main/resources/people.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]
  • 查看DataFrame的Schema信息
scala> df.printSchema
root
 |-- age: long (nullable = true)
 |-- name: string (nullable = true)
  • 只查看"name"列数据
scala> df.select("name").show
+-------+
|   name|
+-------+
|Michael|
|   Andy|
| Justin|
+-------+
  • 查看"username"列数据以及"age+1"数据

注意:涉及到计算的时候,每列都必须使用$,或者采用引号表达式:单引号+字段名

scala> df.select($"name", $"age" + 1).show
+-------+---------+
|   name|(age + 1)|
+-------+---------+
|Michael|     null|
|   Andy|       31|
| Justin|       20|
+-------+---------+


scala> df.select('name, 'age + 1).show
+-------+---------+
|   name|(age + 1)|
+-------+---------+
|Michael|     null|
|   Andy|       31|
| Justin|       20|
+-------+---------+


scala> df.select('name, 'age + 1 as "newAge").show
+-------+------+
|   name|newAge|
+-------+------+
|Michael|  null|
|   Andy|    31|
| Justin|    20|
+-------+------+
  • 查看"age"大于"30"的数据
scala> df.filter('age >= 30).show
+---+----+
|age|name|
+---+----+
| 30|Andy|
+---+----+


scala> df.filter($"age" >= 30).show
+---+----+
|age|name|
+---+----+
| 30|Andy|
+---+----+
  • 按照"age"分组,查看数据条数
scala> df.groupBy("age").count.show
+----+-----+
| age|count|
+----+-----+
|  19|    1|
|null|    1|
|  30|    1|
+----+-----+

RDD转换为DataFrame

在IDEA中开发程序时,如果需要RDD与DF或者DS之间相互操作,那么需要引入import spark.implicits._
这里的spark不是Scala中的包名,而是创建的SparkSession对象的变量名称,所以必须先创建SparkSession对象再导入。
这里的spark对象不能使用var声明,因为Scala只支持val修饰的对象的引入
spark-shell中无需导入,自动完成此操作。

scala> val peopleRDD = sc.textFile("examples/src/main/resources/people.txt")
peopleRDD: org.apache.spark.rdd.RDD[String] = examples/src/main/resources/people.txt MapPartitionsRDD[150] at textFile at <console>:24

scala> peopleRDD.toDF("line").show
+-----------+
|       line|
+-----------+
|Michael, 29|
|   Andy, 30|
| Justin, 19|
+-----------+

实际开发中,一般通过样例类将RDD转换为DataFrame

scala> case class User(name: String, age: Int)
defined class User

scala> sc.makeRDD(List(("dsy", 18), ("sarah", 19))).map(t => User(t._1, t._2)).toDF.show
+-----+---+
| name|age|
+-----+---+
|  dsy| 18|
|sarah| 19|
+-----+---+

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值