sparksql对于数据的读写操作

spark获取dataframe的三种方法

将RDD转为dataframe

1.方法一:使用反射的方式去推断RDD的schema信息,这种方法的前提是你已经知道了schema。具体的操作代码如下


import org.apache.spark.sql.SparkSession
object DFApp {
  def main(args: Array[String]): Unit = {
    val sparkSession=SparkSession
      .builder()
      .appName("DFApp")
      .master("local[2]")
      .getOrCreate()
inferReflection(sparkSession)
sparkSession.stop()
  }
  //定义一个反射函数
  def inferReflection(sparkSession:SparkSession)={
    //创建一个RDD
    val info=sparkSession.sparkContext.textFile("file:///C:\\Users\\HJ\\Desktop/secondhomework.txt")
    import sparkSession.implicits._
    //要转为dataframe,必须要导入隐式转换
    val df=info.map(_.split("\t")).map(x=>Info(x(0),x(2).toLong)).toDF()
    //x(0),x(2)要和Info(domin: String, responseSize: Long)里面的字段类型对应上,亲测不对应也会报错
  //把rdd转为dataframe之后,你可以使用dataframe的APi进行操作,也可以使用sql(先注册成一张表)
    df.createOrReplaceTempView("info1")//把dataframe注册成一个临时表叫做info1
//    sparkSession.sql("select domin,sum(responseSize)as a from info1 group by domin").show()
    val infoDF=sparkSession.sql("select domin,sum(responseSize)as a from info1 group by domin")
    //sparkSession.sql的返回值是dataframe,dataframe也有map操作,dataframe里面的函数基本和RDD一样
    //infoDF.map(x=>"name: "+x(0)).show()//对dataframe做map操作后返回的是dataset,通过控制台可以看到其返回的具体类型。1.6版本的时候返回值还是RDD
    //infoDF.map(x=>x(0)).show()(这样写就会报错)
    //infoDF.rdd.map(x=>x(0)).collect().foreach(println)//如果想这样使用map,得通过rdd把它转为RDD
    infoDF.map(x=>x.get(0)).collect().foreach(println)//这种也不行
    //原因是dataframe通过map后变为dataset的类型,dataset是强类型,所以会报错,
    // 因为字段已经通过caseclass提前规定了类型了,所以只需要把类型强转为caseclass提前规定的类型或者转为RDD就可以解决报错    ,如下将dataframe转为rdd或者获取domin字段并将其转为String类型就可以解决报错
 //infoDF.rdd.map(x=>x.get(0)).collect().foreach(println)//这样可以打印出第一个字段的值
    infoDF.rdd.map(x=>x.getAs[String]("domin")).collect().foreach(println)
    //这样可以得到domin字段的值
 //infoDF.rdd.map(x=>x.getAs[String]("domin")).collect().foreach(println)
 //这样可以得到domin字段的值
  }
}
case class Info(domin: String, responseSize: Long)//该类被定义用来做反射类,定义表的schema信息

2.方法二:通过编程指定schema
据官网介绍,表结构提前不知道的情况下,就可以通过编程指定schema,将rdd转为dataframe,具体的操作diamante如下。

该方法一般有三个步骤:
a. Create an RDD of Rows from the original RDD
b. Create the schema represented by a StructType matching the structure of Rows in the RDD created in Step 1
c. Apply the schema to the RDD of Rows via createDataFrame method provided by SparkSession


import org.apache.spark.sql.types._
import org.apache.spark.sql.{Row, SparkSession}
object DFApp1 {
  def main(args: Array[String]): Unit = {
    val sparkSession=SparkSession
      .builder()
      .appName("DFApp1")
      .master("local[2]")
      .getOrCreate()
programmatically(sparkSession)
    sparkSession.stop()
  }
def programmatically(sparkSession: SparkSession)={
    val info=sparkSession.sparkContext.textFile("file:///C:\\Users\\HJ\\Desktop/secondhomework.txt")
    val rdd =info.map(_.split("\t")).map(x=>Row(x(0),x(2).toLong))
    //步骤一:创建一个RDD[Row]类型从原始的RDD转成的
    val struct=
      StructType(Array(
        StructField("domin", StringType,true),
        StructField("responseSize", LongType, false)
        ))
    //步骤二:创建schema
    val df=sparkSession.createDataFrame(rdd,struct) 
 //步骤三:把schema作用到RDD[Row]上面。createDataFrame(RDD[Row],StructType)
      df.show()

直接读取hive表,将读入的数据直接转为dataframe

具体的操作代码如下:


import org.apache.spark.sql.SparkSession
object DFApp2 {
  def main(args: Array[String]): Unit = {
    val sparkSession=SparkSession.builder()
      .appName("DFApp2 ")
      .enableHiveSupport()//使用到hive一定要开启这个,idea要想连接hive得在pom中加上hive
      .master("local[2]")
      .getOrCreate()
   //val g6= sparkSession.table("product_info")//Unable to instantiate SparkSession with Hive support because Hive classes are not found 一开始报了这个错误,因为enableHiveSupport()没有加上
   //括号里面直接是表,然后读出表的内容作为dataframe
    val gg=sparkSession.sql("show databases")//括号里面是具体的操作表的语句
    gg.show
sparkSession.stop()//具体的连接hive可以参考我之前的文章,spark通过idea连接hive

  }
}

spark通过外部数据源直接获取后转为dataframe

根据官网介绍,spark可以直接读取多种格式的数据转为dataframe。操作代码如下:

import org.apache.spark.sql.{SaveMode, SparkSession}
object DataSourceAPIApp {
  def main(args: Array[String]): Unit = {
    val sparkSession=SparkSession.builder()
      .master("local[2]")
      .enableHiveSupport()
      .appName("DataSourceAPIApp")
      .getOrCreate()
    //标准读写法,通过scala控制台演示
    //sparkSession.read.format("text").load("hdfs://192.168.2.65:9000/data/users.txt").show()
    //load支持传一个或者多个路径,这样读出的文本内容都放在一个value字段下面
    //format里面包括有text/json/parquet/jdbc..
//简化读写法,通过scala控制台演示sparkSession用spark代替
//sparkSession.read.text().show
//text()也支持传一个或者多个路径
//这种写法默认只能读parquet格式,其他格式需要在conf中设置
//例如:[hadoop@hadoop001 bin]$./spark-shell --conf spark.sql.sources.default="text"/text
//sparkSession.read.load()
//其他读写法
//sparkSession.read.format("text").option("path","").load().show

   val df=sparkSession.read.format("parquet").load("hdfs://192.168.2.65:9000/data/users.parquet")
//读jdbc文件
   //以读mysql为例
/*    val jdbcDF=sparkSession.read.format("jdbc")
      .option("url","jdbc:mysql://192.168.2.65:3306/")
      .option("dbtable","ruoze_d5.tbls")
      //.option("dbtable","ruozedata5.city_info")//前面是数据库,后面是表,可以读出来
      //写两个option一下读两个表是无法成功的,一次只能读一个表
        .option("user","root")
        .option("password","******")
        .load()
sparkSession.stop()
  }
}

spark将dataframe写出去

具体操作代码如下:

import org.apache.spark.sql.{SaveMode, SparkSession}
object DataSourceAPIApp {
  def main(args: Array[String]): Unit = {
    val sparkSession=SparkSession.builder()
      .master("local[2]")
      .enableHiveSupport()
      .appName("DataSourceAPIApp")
      .getOrCreate()
val df=sparkSession.read.format("parquet").load("hdfs://192.168.2.65:9000/data/users.parquet")
// df.write.format("json").save("")
 //输出保存路径文件夹已经存在使用不同的保存格式
 //mode(SaveMode.Overwrite)需要导包,里面是SaveMode类型
// df.write.format("json").mode(SaveMode.Overwrite).save("hdfs://192.168.2.65:9000/data/jsonfile")
//指定到文件夹

 //mode("")不需要导包,里面是字符串类型
// df.write.format("text").mode("").save()

 //把读进来的文件存为表
// df.select("name").write.saveAsTable("")
 //df.write.format("parquet")
  // .option("path","/user/hive/warehouse")
  //做了这个操作后,/user/hive/warehouse下面只有一个TXT文件,也就是说之前的内容
  // 全部被重写了,也就意味着全部丢失了
  // .option("path","/user/hive/warehouse/ruoze_spark_parquett1")
  // .mode("overwrite")
  // .saveAsTable("ruoze_spark_parquett1")
 //把表名也写到内部表的存储路径下,这样在hive里面就能够查到表了。我认为是
 // 把内容写进到表里面去的原因
    df.write.format("orc")
      .option("path","/user/hive/warehouse/ruoze_spark_orc")
        .mode("overwrite")
        .saveAsTable("ruoze_spark_orc")
      //读的是parquet格式,写到hive表的时候可以是parquet,也可以是其他格式,比如orc格式


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值