SparkSql优化-读取MySql慢优化-写入MySql慢优化-表关联注意

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

SparkSqk读mysql计算写入mysql的踩坑和优化记录


一、SparkSql读取mysql慢优化

spark执行的时候非常慢首先观察的是spark的UI界面找到哪个地方慢在刚开始的时候就卡着不动,多半是spark读取mysql过慢

SELECT * FROM information_schema.processlist WHERE command='Query' ORDER BY time desc;

查看mysql的进程,在spark读取的表的库里面执行,找到spark读取的表观察读取sql,和执行时间,是否锁表,是否使用索引
他这里是一个链接在读取数据,可以增加读取mysql的链接数

    val order: DataFrame = spark.read
      .format("jdbc")
      .option("url", ConnInfoUtils.getAddress("MG", "dw-product",1,"1"))
      .option("dbtable", "dim_variant_order_day")
      .option("user", ConnInfoUtils.getUserPassword("user"))
      .option("password", ConnInfoUtils.getUserPassword("password"))
      .option("driver", ConnInfoUtils.getUserPassword("driver"))
      .option("numPartitions", 50)
      .option("partitionColumn", "id")
      .option("lowerBound", "1")
      .option("upperBound", "9000000")
      .load()
    order.createOrReplaceTempView("dim_variant_order_day")

参数介绍
dbtable: 表名
url/user/password/driver :数据库链接信息
numPartitions :预期的分区数
lowerBound:分区列的最小值
upperBound:分区列的最大值
partitionColumn:用于分区的列,必须是数字类型和时间类型
partitionColumn这里数值类型自增的最好
如果使用时间分区报错解决不了可以使用一下方式

         //时间分片
      val ymdFormat = new SimpleDateFormat("yyyy-MM-dd")
      val day1: Calendar = Calendar.getInstance()
      val start: Date = ymdFormat.parse("2020-01-01")
      //开始时间 结束时间 切分天数 分区字段
      val strings2: util.List[String] = DateSplitUtils.splitByDay(start,day1.getTime, 30,"createDate")
      val str3: String = strings2.toArray().mkString(",")
      val predicates: Array[String] = str3.split(",")
/*
 val predicates = Array[String]("createDate < '2019-01-01'",
      "createDate>='2019-01-01' and createDate<'2020-01-01'",
      "createDate>='2020-01-01' and createDate<'2020-02-01'",
      "createDate>='2020-02-01' and createDate<'2020-03-01'",
      "createDate>='2020-03-01' and createDate<'2020-04-01'",
      "createDate>='2020-04-01'"
*/
      //在链接里面多加入Array[String]的参数
      val associated: DataFrame = spark.read.jdbc(ConnInfoUtils.getAddress("MG", "dsp", 1, "1"), "db_accproduct", predicates, ConnInfoUtils.getProperties())
      associated.createOrReplaceTempView("db_accproduct")

在链接里面加入 Array[String] predicates参数,对表里面的时间进行切分在读取的时候会按照自定义的时间段去取区数据

在读取的时候一定要多关注mysql的链接信息和spark的ui界面关注读取速率

二、spark写入mysql数据慢

在写入的时候要关注mysql的链接数量,和写入sql是否是批量和链接数量是否过少

1.批量写入mysql数据

修改链接mysql的url开启批量写入,这里多条输入据合并到一个insert语句里面,url里面添加 &rewriteBatchedStatements=true

jdbc:mysql://192.168.4.22:3306/dsp?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&autoReconnect=true&useSSL=false&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai

2.计算完之后在重新分区,防止数据倾斜写入的时候特别慢

在sql后面加入 distribute by rand()

3.调整shuffle的分区数量

config("spark.sql.shuffle.partitions","500")

三、SparkSql关联查的坑

1.spark 区分大小写 mysql不区分,关联查的时候尽量都转大写,并且要去除前后空格

on trim(upper(t1.SKU))=trim(upper(t5.sku))

2.SparkSql时区问题

spark 指定时区后,可能不造成数据计算错误和mysql不一致,数据链接时区、代码指定时区、运行指定时区 这几个一定要一样,在计算结果后一定要校验计算前和计算后的时间
spark 的date和to_date等时间处理函数,会自动对时间进行时区转化,

3.spark在进行比较或者过滤的时候是区分类型的

mysql在对 数值类型比较的时候 可以 用 <>’’ 不等于空串 这个是不起作用的
可以用 not in(’’,0)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值