Spark学习(二)-SparkSQL

本文详细介绍了SparkSQL的核心概念及使用方法,包括SparkSession、SQLContext、HiveContext的创建与应用,DataFrame的生成与操作,以及如何通过SparkSQL连接并操作Hive数据。

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

安装单机的spark,之前那个太复杂了
https://blog.youkuaiyun.com/zhaohaibo_/article/details/84260310

SprakSession

Spark有三大引擎,Spark core,SparkSQL,SparkStreaming
Spark core的关键抽象是SparkContext,RDD;
Spark SQL的关键抽象是SparkSession,DataFrame;
SparkStreaming的关键抽象是StreamingContext,DStream

SparkSession 是 spark2.0 引入的概念,主要用在 sparkSQL 中,当然也可以用在其他场合,他可以代替 SparkContext;
SparkSession 其实是封装了 SQLContext 和 HiveContext

SQLContext

它是SparkSQL的入口点,sparkSQL的应用必须创建一个SQLContex或者HiveContext的类实例

from pyspark import SparkContext, SparkConf
from pyspark.sql import SparkSession, SQLContext, HiveContext

conf = SparkConf().setAppName('test').setMaster('yarn')
sc = SparkContext(conf=conf)

sqlc = SQLContext(sc)
print(dir(sqlc))
# 'cacheTable', 'clearCache', 'createDataFrame', 'createExternalTable', 'dropTempTable', 'getConf', 'getOrCreate', 'newSession', 'range', 'read', 'readStream',
# 'registerDataFrameAsTable', 'registerFunction', 'registerJavaFunction', 'setConf', 'sparkSession', 'sql', 'streams', 'table', 'tableNames', 'tables', 'udf', 'uncacheTable'

### sqlcontext 读取数据也自动生成 df
data = sqlc.read.text('/usr/yanshw/test.txt')
print(type(data))
HiveContext

它是SparkSQL的另一个入口点,它继承自SQLContext,用于处理hive中的数据
HiveContext对SQLContext进行了扩展,功能要更加强大

  1. 它可以执行HiveSQL和SQL查询
  2. 它可以操作hive数据,并且可以访问HiveUDF
  3. 它不一定需要hive,在没有hive环境时也可以使用HiveContext
    如果要处理hive数据,需要把hive的hive-site.xml文件放到spark/conf下,HiveContext将从hive-site.xml中获取hive配置信息,如果HiveContext没有找到hive-site.xml,他会在当前目录下创建spark-warehouse和metastore_db两个个文件
from pyspark import SparkContext, SparkConf
from pyspark.sql import SparkSession, SQLContext, HiveContext

conf = SparkConf().setAppName('test').setMaster('yarn')
sc = SparkContext(conf=conf)
## 需要把 hive/conf/hive-site.xml 复制到 spark/conf 下
hivec = HiveContext(sc)
print(dir(hivec))
# 'cacheTable', 'clearCache', 'createDataFrame', 'createExternalTable', 'dropTempTable', 'getConf', 'getOrCreate', 'newSession', 'range', 'read', 'readStream','refreshTable',
# 'registerDataFrameAsTable', 'registerFunction', 'registerJavaFunction', 'setConf', 'sparkSession', 'sql', 'streams', 'table', 'tableNames', 'tables', 'udf', 'uncacheTable'

data = hivec.sql('''select * from hive1101.person limit 2''')
print(type(data))
SparkSession

实现了对二者的封装
SparkSession的创建

class SparkSession(__builtin__.object):
     def __init__(self, sparkContext, jsparkSession=None):
     ''' Creates a new SparkSession.
     |
     |      >>> from datetime import datetime
     |      >>> spark = SparkSession(sc)
     |      >>> allTypes = sc.parallelize([Row(i=1, s="string", d=1.0, l=1,
     |      ...     b=True, list=[1, 2, 3], dict={"s": 0}, row=Row(a=1),
     |      ...     time=datetime(2014, 8, 1, 14, 1, 5))])
     |      >>> df = allTypes.toDF()
     |      >>> df.createOrReplaceTempView("allTypes")
     |      >>> spark.sql('select i+1, d+1, not b, list[1], dict["s"], time, row.a '
     |      ...            'from allTypes where b and i > 0').collect()
     |      [Row((i + CAST(1 AS BIGINT))=2, (d + CAST(1 AS DOUBLE))=2.0, (NOT b)=False, list[1]=2,             dict[s]=0, time=datetime.datetime(2014, 8, 1, 14, 1, 5), a=1)]
     |      >>> df.rdd.map(lambda x: (x.i, x.s, x.d, x.l, x.b, x.time, x.row.a, x.list)).collect()
     |      [(1, u'string', 1.0, 1, True, datetime.datetime(2014, 8, 1, 14, 1, 5), 1, [1, 2, 3])]'''

示例代码

from pyspark.sql import SparkSession


### method 1
sess = SparkSession.builder \
    .appName("aaa") \
    .config("spark.driver.extraClassPath", sparkClassPath) \
    .master("local") \
    .enableHiveSupport() \  # sparkSQL 连接 hive 时需要这句
    .getOrCreate()      # builder 方式必须有这句

### method 2
conf = SparkConf().setAppName('myapp1').setMaster('local[4]')   # 设定 appname 和 master
sess = SparkSession.builder.config(conf=conf).getOrCreate() # builder 方式必须有这句

### method 3
from pyspark import SparkContext, SparkConf
conf = SparkConf().setAppName('myapp1').setMaster('local[4]')   # 设定 appname 和 master
sc = SparkContext(conf=conf)
sess = SparkSession(sc)

文件数据源

from pyspark import SparkContext, SparkConf
from pyspark.sql import SparkSession, SQLContext, HiveContext

conf = SparkConf().setAppName('test').setMaster('yarn')
sc = SparkContext(conf=conf)

#### 替代了 SQLContext 和 HiveContext,其实只是简单的封装,提供了统一的接口
spark = SparkSession(sc)
print(dir(spark))
# 很多属性,我把私有属性删了
# 'Builder','builder', 'catalog', 'conf', 'createDataFrame', 'newSession', 'range', 'read', 'readStream','sparkContext', 'sql', 'stop', 'streams', 'table', 'udf', 'version'

### sess 读取数据自动生成 df
data = spark.read.text('/usr/yanshw/test.txt')      #read 可读类型 [ 'csv', 'format', 'jdbc', 'json', 'load', 'option', 'options', 'orc', 'parquet', 'schema', 'table', 'text']
print(type(data))       # <class 'pyspark.sql.dataframe.DataFrame'>

Hive数据源

## 也需要把 hive/conf/hive-site.xml 复制到 spark/conf 下
spark = SparkSession.builder.appName('test').master('yarn').enableHiveSupport().getOrCreate()

hive_data = spark.sql('select * from hive1101.person limit 2')
print(hive_data)        # DataFrame[name: string, idcard: string]

SparkSQL直接连接到hive

 def main(args: Array[String]): Unit = {
 
    val Array(inpath, dt, hour) = args
 
 
    val conf = new SparkConf().setAppName(this.getClass.getSimpleName)
      //.setMaster("local[*]")
      .setMaster("spark://192.168.40.52:7077")
    val session = SparkSession.builder()
      .config(conf)
      // 指定hive的metastore的端口  默认为9083 在hive-site.xml中查看
      .config("hive.metastore.uris", "thrift://192.168.40.51:9083")
      //指定hive的warehouse目录
      .config("spark.sql.warehouse.dir", "hdfs://192.168.40.51:9000/user/hive/warehouse")
      //直接连接hive
      .enableHiveSupport()
      .getOrCreate()
 
 
    import session.implicits._
 
    val df1 = session.read.parquet(inpath)
    //df1.write.saveAsTable(s"tmp.tmp_app_log_1")
    df1.createOrReplaceTempView("tmp_app_log_test")
 
       //sql的代码省略
    val sql1 =
      s"""
         |select *
         |from tmp_app_log_test
       """.stripMargin
 
 
    val hive_table = "dwb2.fact_mbk_offline_log_mbk_app_action_event_v2_i_h"
    val sql2 = s"alter table $hive_table add  if not exists partition ( dt='$dt',hour='$hour')"
    session.sql(sql2)
 
    val tmp_table =s"""tmp.app_log_${dt}_${hour}"""
    val sql3 = s"""drop table IF EXISTS $tmp_table""".stripMargin
    session.sql(sql3)
 
    val df2 = session.sql(sql1)
    //结果先写入临时表
    df2.write.saveAsTable(tmp_table)
 
 
    //结果从临时表写入分区表
    val sql4 =
      s"""INSERT OVERWRITE TABLE $hive_table
         |PARTITION( dt='$dt',hour='$hour')
         | select * from $tmp_table  """.stripMargin
 
    session.sql(sql4)
 
    val sql5 = s"""drop table IF EXISTS $tmp_table""".stripMargin
    session.sql(sql5)
  }

SparkSQL之DataFrame操作大全

Spark SQL中的DataFrame类似于一张关系型数据表,在关系型数据库中对单表或进行的查询操作,在DataFrame中都可以通过调用其API接口来实现

DataFrame对象的生成

Spark-SQL可以以其他RDD对象、parquet文件、json文件、hive表,以及通过JDBC连接到其他关系型数据库作为数据源来生成DataFrame对象。本文将以MySQL数据库为数据源,生成DataFrame对象后进行相关的DataFame之上的操作。
源码

object DataFrameOperations {
  def main (args: Array[String ]) {
    val sparkConf = new SparkConf().setAppName( "Spark SQL DataFrame Operations").setMaster( "local[2]" )
    val sparkContext = new SparkContext(sparkConf)

    val sqlContext = new SQLContext(sparkContext)
    val url = "jdbc:mysql://m000:3306/test"

    val jdbcDF = sqlContext.read.format( "jdbc" ).options(
      Map( "url" -> url,
        "user" -> "root",
        "password" -> "root",
        "dbtable" -> "spark_sql_test" )).load()

    val joinDF1 = sqlContext.read.format( "jdbc" ).options(
      Map("url" -> url ,
        "user" -> "root",
        "password" -> "root",
        "dbtable" -> "spark_sql_join1" )).load()

    val joinDF2 = sqlContext.read.format( "jdbc" ).options(
      Map ( "url" -> url ,
        "user" -> "root",
        "password" -> "root",
        "dbtable" -> "spark_sql_join2" )).load()

    ... ...
  }
}
DataFrame对象上Action操作
  1. show:展示数据
    以表格的形式在输出中展示jdbcDF中的数据,类似与select * from spark_sql_test的功能
    show方法有四种调用方式
    (1)show
    只显示前20条记录
    示例
    jdbcDF.show
    (2)show(numRows:Int)
    显示numRows条
    示例
    jdbcDF.show(3)
    (3)show(truncate:Boolean)
    显示最多只显示20个字符,默认为true
    示例
    jdbcDF.show(true)
    jdbcDF.show(false)
    (4)show(numRows:Int,truncate:Boolean)
    综合前面的显示记录条数,以及对过长字符串的显示格式
    示例
    jdbcDF.show(3,false)

  2. collect:获取到所有数据到数组
    不同于前面的show方法,这里的collect方法会将jdbcDF中的所有数据都获取到,并返回一个Array对象
    jdbcDF.collect()

  3. collectAsList:获取所有数据到list
    功能和collect类似,只不过将返回结构变成list对象
    jdbcDF.collectAsLIst

4.describe(cols:String*):获取指定字段的统计信息
可以动态传入一个或多个String类型的字段名,结果仍为DataFrame对象,用于统计数值类型字段的统计值,比如count,mean,stddev,min,max等
使用方法如下,其中c1字段为字符类型,c2字段为整型,c4字段为浮点型
JdbcDF.describe(“c1”,”c2“,”c4“).show()
在这里插入图片描述

5.first,head,take,takeAsList:获取若干数据
这里列出的四个方法比较类似,其中
first获取第一行记录
head获取第一行记录,head(n:Int)获取前n行记录
take(n:Int)获取前n行数据
takeAsList(n:Int)获取前n行数据,并以LIst的形式展现
以Row或者Array[Row]的形式返回一行或多行数据。first和head功能相同。
  take和takeAsList方法会将获得到的数据返回到Driver端,所以,使用这两个方法时需要注意数据量,以免Driver发生OutOfMemoryError

DataFrame对象上的条件查询和join等操作

返回的对象是DataFrame类型的方法,可以连续调用

  1. where条件相关
    传入筛选条件表达式,可以用and和or。得到DataFrame类型的返回结果,
      示例:

jdbcDF .where(“id = 1 or c1 = ‘b’” ).show()

filter:根据字段进行筛选
传入筛选条件表达式,得到DataFrame类型的返回结果。和where使用条件相同
  示例:

jdbcDF .filter(“id = 1 or c1 = ‘b’” ).show()

  1. 查询指定条件
    (1)select:获取指定字段值
    根据传入的String类型字段名,获取指定字段的值,以DataFrame类型返回
      示例:

jdbcDF.select( “id” , “c3” ).show( false)

有一个重载的select方法,不是传入String类型参数,而是传入Column类型参数。可以实现select id, id+1 from test这种逻辑。

jdbcDF.select(jdbcDF( “id” ), jdbcDF( “id”) + 1 ).show( false)
需求更改不用在学习了
原文:https://blog.youkuaiyun.com/dabokele/article/details/52802150

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值