spark将rdd转为string_Spark 系列(八)SparkSQL和集成数据源及简单优化方案简化工作的利器!!...

本文介绍了SparkSQL的Catalyst Optimizer及其优化流程,展示了如何通过优化逻辑计划和物理计划提高性能。内容包括Spark SQL API的使用、DataFrame与DataSet操作、集成Parquet和Hive数据源、MySQL数据源的操作以及UDF的使用。此外,还探讨了多种Spark性能优化策略,如序列化、避免嵌套结构和减少中间结果的生成等。
摘要由CSDN通过智能技术生成

文章目录

    • SparkSQL和集成数据源-及简单优化:

      • SparkSQL优化器--Catalyst Optimizer

        • 具体流程:

      • Spark SQL API :

      • 具体优化流程:

        • 原流程:

        • 优化流程:

      • DataSet与DataFrame操作

      • Spark SQL操作外部数据源

        • Parquet文件:

        • Hive数据源集成:

        • Mysql数据源集成:

      • Spark函数UDF使用:

      • Spark性能优化

        • 一:序列化:

        • 二:使用对象数组

        • 三:避免嵌套结构

        • 四:尽量使用数字作为Key,而非字符串

        • 五:以较大的RDD使用MEMORY_ONLY_SER

        • 六:加载CSV、JSON时,仅加载所需字段

        • 七:仅在需要时持久化中间结果(RDD/DS/DF)

        • 八:避免不必要的中间结果(RDD/DS/DF)的生成

        • 九:DF的执行速度比DS快约3倍

SparkSQL和集成数据源-及简单优化:

SparkSQL优化器—Catalyst Optimizer

Catalyst是Spark SQL的核心

a350251075ab72a41163bdfb4a778505.png

Catalyst OptimizerCatalyst优化器,将逻辑计划转为物理计划

具体流程:
  • 代码转化为逻辑计划

  • 优化

    • 在投影上面查询过滤器

    • 检查过滤是否可下压

  • 转化为物理计划

Spark SQL API :

  • SparkContext

  • SQLContext

    • Spark SQL编程入口

  • HiveContext

    • SQLContext的子集,包含更多功能

  • SparkSession

具体优化流程:

原流程:
select name from(    select id,name from people
) pwhere p.id = 1
  1. 先运行子查询

  2. 开始scan people

  3. 选择字段id,name

  4. 运行where,filter掉id字段

  5. 选择字段name

优化流程:
  • 在投影(select)上面查询过滤器

  • 检查过滤是否可下压

  1. 先运行子查询

  2. 开始scan people

  3. 运行where,filter掉id字段

  4. 选择字段name

d370d1598e169b263922664912587cf7.png

DataSet与DataFrame操作

  • DataSet =  RDD + Schema

    • 特定域对象中的强类型集合

createDataset()的参数可以是:SeqArrayRDD

case class Point(label:String,x:Double,y:Double)case class Category(id:Long,name:String)
val pointsRDD=sc.parallelize(List(("bar",3.0,5.6),("foo",-1.0,3.0)))
val categoriesRDD=sc.parallelize(List((1,"foo"),(2,"bar")))
val points=pointsRDD.map(line=>Point(line._1,line._2,line._3)).toDS
val categories=categories.map(line=>Category(line._1,line._2)).toDS
points.join(categories,points("label")===categories("name")).show

142ba097e51d89f64be5968e0fbd69eb.png

  • DataFrame = DataSet[Row]

    • struct

    • map

    • array

    • 类似二维表格

    • 在RDD基础上加入了Schema数据结构信息

    • DataFrame Schema支持嵌套数据类型

Spark SQL操作外部数据源

  • Parquet文件:

    是一种流行的列式存储格式,以二进制存储,文件中包含数据与元数据

    val schema=StructType(Array(StructField("name",StringType),
    StructField("favorite_color",StringType),
    StructField("favorite_numbers",ArrayType(IntegerType))))
    val rdd=sc.parallelize(List(("Alyssa",null,Array(3,9,15,20)),("Ben","red",null)))
    val rowRDD=rdd.map(p=>Row(p._1,p._2,p._3))
    val df=spark.createDataFrame(rowRDD,schema)
    df.write.parquet("/data/users") //在该目录下生成parquet文件
    val df=spark.read.parquet("/data/users")    //该目录下存在parquet文件df.show
    df.printSchema
    • 读parquet文件

    • 写parquet文件

  • Hive数据源集成:

    1hive-site.xml,core-site.xml
    hdfs-site.xml拷贝至
    resource包

    2、导porn.xml依赖包

    3、自行创建SparkSession,启用Hive支持

        
    <dependency>
    <groupId>org.apache.sparkgroupId>
    <artifactId>spark-hive_2.11artifactId>
    <version>2.3.4version>
    dependency>
    val spark = SparkSession.builder()
    .appName("wyw")
    .master("local[*]")
    .enableHiveSupport()
    .getOrCreate()
    • Hive在idea配置:

  • Mysql数据源集成:
    $spark-shell --jars /opt/spark/ext_jars/mysql-connector-java-5.1.38.jar

    val url = "jdbc:mysql://localhost:3306/metastore"val tableName = "TBLS"// 设置连接用户、密码、数据库驱动类val prop = new java.util.Properties
    prop.setProperty("user","hive")
    prop.setProperty("password","mypassword")
    prop.setProperty("driver","com.mysql.jdbc.Driver")// 取得该表数据val jdbcDF = spark.read.jdbc(url,tableName,prop)
    jdbcDF.show//DF存为新的表jdbcDF.write.mode("append").jdbc(url,"t1",prop)

Spark函数UDF使用:

  • SparkSession.udf.register():

    只在sql()中有效

import spark.implicits._//注册自定义函数,注意是匿名函数spark.udf.register("hobby_num", (s: String) => s.split(',').size)
spark.sql("select name, hobbies, hobby_num(hobbies) as hobby_num from hobbies").show
  • functions.udf():

    对DataFrame API均有效

val scoreTransaction = udf{score: String => {
score.toInt match { case x if x > 85 => "A"
case x if x > 70 => "B"
case x if x > 60 => "C"
case _ => "D"
}
}

Spark性能优化

一:序列化:

java序列化,spark默认方式

  • kryo序列化,比java序列化快约10倍

conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer");//向Kryo注册自定义类型conf.registerKryoClasses(Array(classOf[MyClass1], classOf[MyClass2]));

如果没有注册需要序列化的class,Kyro依然可以照常工作,但会存储每个对象的全类名(full class name),这样往往比默认的 Java serialization 浪费空间

二:使用对象数组
三:避免嵌套结构
四:尽量使用数字作为Key,而非字符串
五:以较大的RDD使用MEMORY_ONLY_SER
六:加载CSV、JSON时,仅加载所需字段
七:仅在需要时持久化中间结果(RDD/DS/DF)
八:避免不必要的中间结果(RDD/DS/DF)的生成
九:DF的执行速度比DS快约3倍
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值