SparkSQL之入门

SparkSQL

SparkSession

  • SparkSession是SparkSQL的编程入口
//SparkSession通过SparkSession.builder()构建
    val spark=SparkSession.builder()
      .master("local[2]")
      .appName("start")
      .getOrCreate()

SparkSQL数据抽象

  • SparkSQL的数据抽象有df和ds两种

DataFrames

  • 产生版本:Spark1.3.0
    DataFrames列已命名的Dataset。相当于关系型数据库的表,R/Python的data frame,但底层做了更丰富的优化。它可从结构化数据文件、hive表、其他数据库、RDD创建。在API层面,DataFrame表现为多个Row的Dataset,比如在scala API里,DataFrame 类型为 Dataset[Row],而在Java里则是Dataset<Row>。
DataFrames的创建

使用SparkSession,应用程序可从已知的RDD、Hive表、其他spark数据源如(文本文件,json文件等)创建。

// 通过SparkSession读取json文件,创建DF对象
    val df1=spark.read.format("json").load("amos/src/main/resources/sparksql/employees.json")
    // 通过SparkSession读取文本文件,创建DF对象
    val df2=spark.read.text("amos/src/main/resources/sparksql/people.txt")
	// 把这个DataFrame 注册为一个 SQL 临时视图
    df1.createOrReplaceTempView("t1")
    spark.sql("select * from t1").show(5)
/*
+-------+------+
|Michael|  3000|
|   Andy|  4500|
| Justin|  3500|
|  Berta|  4000|
+-------+------+
*/
DataFrames的DSL操作

DataFrame操作,又叫无类型的Dataset操作

//导入$符号的使用
    import spark.implicits._
    //查询单列
    df1.select("name")
    // 查询每一条记录, 但 工资 乘 10
    df1.select($"name", $"salary" * 10)
    //条件查询
    df1.select("name").where($"salary">=4000)
      .show()
    //另一种写法
    //df1.filter($"salary">=4000).show()
	/*
	最后一次的输出:
	| name|
	+-----+
	| Andy|
	|Berta|
	+-----+

	+-----+------+
	| name|salary|
	+-----+------+
	| Andy|  4500|
	|Berta|  4000|
	+-----+------+
	*/

DataSets

  • 产生版本:Spark1.6.0
    Datasets分布式数据集。提供了RDD的优点(强类型、强大的lambda函数)和Spark-SQL优化了的执行引擎。它可由JVM对象创建,然后使用函数式转换进行修改,比如map、flatmap、filter等。

三种数据抽象的使用

三种数据抽象的概念和区别

  • RDD
1.RDD[T]  T类型规定了RDD中存放的数据类型
  • DataFrames
    2.DataFrame=Dataset[Row]
   val df1: DataFrame = spark.read.json("\\src\\main\\resources\\sparksql\\people.json")
   // df本质上是ds的一个特例,即Row作为泛型的ds
   // type DataFrame = Dataset[Row]
   // Row是一个特质(接口)
   // trait Row extends Serializable {
   // Row的一个实现类是GenericRow
   // class GenericRow(val values: Array[Any]) extends Row {
   //    由于GenericRow不能完全表示数据的字段名和类型,所以使用GenericRowWithSchema
   // class GenericRowWithSchema(
   //    values: Array[Any], override val schema: StructType)
   //  extends GenericRow(values)
   //
   //  case class StructType(val fields: Array[StructField])

   //  case class StructField(
   //    name: String,      字段名
   //    dataType: DataType  字段类型
   //    )

   //  GenericRow有一个成员属性 values : Array[Any] 用来存储表每一行的内容数据
   //  StructType有一个成员属性fields: Array[StructField]

   // Array[StructField](StructField("name",StringType),StructField("age",IntegerType))
  • DataSets
// 3.Dataset[T] 与RDD类似,通常使用样例类作为DS的泛型

//  Dataset直接通过样例类的属性 映射表的字段名和类型

// case class Person(name:String,age:Int)
// Dataset[Person]
汇总

Dataset是对RDD在sql特性上的封装,RDD不能执行sql查询,而DataSet可以。
DataFrame是Dataset的特例,DataFrame = Dataset[Row],DataFrame支持所有Dataset操作,DataFrame每一行是固定Row的类型,只能通过索引或列名访问列值,而Dataset每一行都是明确的类型,访问比较方便。如果行的类型不确定时,使用DataFrame比较合适。

三种数据抽象的相互转换

  • RDD转换
	// 1. RDD转DF
    // 1.1 需要导入sparkSession中的隐式转换
    import spark.implicits._
    // 1.2 将RDD转换成元组的泛型 (String,Int)
    val rdd = sc.textFile("amos/src/main/resources/sparksql/people.txt")
    val rdd1 = rdd.map(x => {
      val str = x.split(",")
      (str(0), str(1).trim.toInt)
    })
    // 1.3 rdd.toDF("第一列列名","第一列列名"...)
    val df = rdd1.toDF("name", "age")
    // 2. RDD转DS
    // 2.1 导入隐式转换
    // 2.2 提前定义一个样例类C,样例类C的属性与字段对应
    // 2.3 将RDD转换成刚才定义的C泛型
    // 2.4 rdd:RDD[C] .toDS  =>   Dataset[C]
    val rdd2 = rdd1.map(x => people(x._1, x._2))
    val ds=rdd2.toDS()
  • DS、DF相互转化
	// 3. DF转DS
    // 3.1 注意df和as[C]的C这个样例类,字段名和字段类型必须一致
    val ds1=df.as[people]

    // 4. DS转DF
    // DS转DF时会自动根据样例类的属性来映射字段名和字段类型
    val df1=ds.toDF()
  • DS、DF转换RDD
	// 5. DS和DF转RDD
    // 直接ds.rdd 或者df.rdd
    // df转成的RDD泛型为Row
    val rdd3=ds.rdd
    val rdd4=df.rdd
    // 从row对象中取出字段值时
    // 由于这些字段值使用Array[Any]进行存储
    // 所以取出时需要进行类型转换才能使用
    // 如果类型转换编写错误,运行时会抛出异常
    // 但是在编译时期无法发现错误,所以DF也被称为类型不安全
    rdd4.map(x=>{
      (x.get(0),x.getInt(1))
    })

三种数据抽象的构建

	// 3.1 rdd通过sc创建
    // 3.2 ds 需要提前声明样例类,之后通过已有的df或者rdd进行转换
    // 3.3 df的创建可以使用SparkSession提供的现有方法,或者自己构造
    // 3.3.1 通过SparkSession创建DF
    //  语法  sparkSession.read.format("数据源类型").load("文件路径")

SparkSQL读写

读取文件

  • read加载数据
// 语法:spark.read.text(文件路径)
// 支持的文件有:csv jdbc json orc parquet text等
val df2 = spark.read.text("amos/src/main/resources/sparksql/people.txt")

注意:加载数据的相关参数需写到上述方法中。如:textFile需传入加载数据的路径,jdbc需传入JDBC相关参数。

  • format指定加载数据类型
   // spark.read.format("文件类型")[.option("…")].load("文件路径")
    val df1 = spark.read.format("json").load("amos/src/main/resources/sparksql/employees.json")
  • 参数详解
  1. format("…"):指定加载的数据类型,包括"csv"、“jdbc”、“json”、“orc”、“parquet"和"textFile”。
  2. load("…"):在"csv"、“orc”、“parquet"和"textFile"格式下需要传入加载数据的路径。
  3. option(”…"):在"jdbc"格式下需要传入JDBC相应参数,url、user、password和 dbtable。

写出文件

  • write保存数据
语法:spark.write
    val df=spark.read.text("C:\\Users\\hushaonan\\Desktop\\logs\\access.log-20190929")
    df.write.text("C:\\Users\\hushaonan\\Desktop\\logs\\output\\test.txt")

注意:保存数据的相关参数需写到上述方法中。如:textFile需传入加载数据的路径,jdbc需传入JDBC相关参数。

  • format指定文件类型
 //df.write.format("…")[.option("…")].save("…")
   df.write.format("json").save("C:\\Users\\hushaonan\\Desktop\\output\\test")
   df.write.format("parquet").save("C:\\Users\\hushaonan\\Desktop\\output\\test1")
   df.write.format("csv").save("C:\\Users\\hushaonan\\Desktop\\output\\test2")
  • 参数详解:

    1. format("…"):指定保存的数据类型,包括"csv"、“jdbc”、“json”、“orc”、“parquet"和"textFile”。
    2. save ("…"):在"csv"、“orc”、“parquet"和"textFile"格式下需要传入保存数据的路径。
    3. option(”…"):在"jdbc"格式下需要传入JDBC相应参数,url、user、password和dbtable
  • 文件保存选项
    可以采用SaveMode执行存储操作,SaveMode定义了对数据的处理模式。SaveMode是一个枚举类,其中的常量包括:

  1. Append:当保存路径或者表已存在时,追加内容;
  2. Overwrite: 当保存路径或者表已存在时,覆写内容;
  3. ErrorIfExists:当保存路径或者表已存在时,报错;
  4. Ignore:当保存路径或者表已存在时,忽略当前的保存操作。
	//df.write.mode(SaveMode.Append).save("… …")
    df.write.mode(saveMode="append").save("C:\\Users\\hushaonan\\Desktop\\logs\\output\\test.txt")
	
	this.mode = saveMode.toLowerCase match {
      case "overwrite" => SaveMode.Overwrite
      case "append" => SaveMode.Append
      case "ignore" => SaveMode.Ignore
      case "error" | "default" => SaveMode.ErrorIfExists
      case _ => throw new IllegalArgumentException(s"Unknown save mode: $saveMode. " +
        "Accepted save modes are 'overwrite', 'append', 'ignore', 'error'.")
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值