spark遇到的问题及解决方法

1. 表中数据过亿,加载速度过慢,而我只需要加载增量数据

如:加载昨天一整天的数据,添加predicates分区,方法如下:

//predicates相当于是把昨天的数据分成一个区,其它的数据不加载
val predicates: Array[String] = Array(s"created_at >=\'" + getDateTime.getYesDate() + "\' and created_at <\'" + getDateTime.getNowDate() + "\'")
// 取得该表数据
val orderInfoDF :DataFrame = spark.read.jdbc(TiDBMysqlUrl, orderInfoTable, predicates, properties)

如果需要加载大表中全部数据,可以把数据分成多个区(读取数据库表默认是一个分区),如下是按创建时间分区,把最近三个月数据分成三个区

val predicates: Array[String] =
      Array(
        "2019-08-01" -> "2019-09-01",
        "2019-09-01" -> "2019-10-01",
        "2019-10-01" -> "2019-11-01"
      ).map {
        case (start, end) =>
          s"pay_status=1 and created_at >=\'$start\' and created_at <\'$end\'"
      }

// 取得该表数据
val orderInfoDF :DataFrame = spark.read.jdbc(TiDBMysqlUrl, orderInfoTable, predicates, properties)

 

2.每次到了最后一个stage,报内存不足错误

原因:

使用了coalesce重设Rdd的分区,可能是分区的数量发生激烈的变化,从父Rdd的几千个分区设置成几个,从而导致这个错误。

方法:

为了避免这个情况,可以设置shuffle=true,即为repartition()方法

有两种方法是可以重设Rdd的分区:分别是 coalesce()和repartition()方法,主要用来合并多个分区,以便生成少数文件

 

3.插入数据到Tidb里面,直接报超过最大限制条数

Caused by: java.sql.SQLException: statement count 5001 exceeds the transact

解决方法:

可以通过修改tidb的配置,然后重启tidb,但由于运维工程师最大设置为50000,怕负载过高,只能通过批量插入到tidb里面;

由于我这边数据大概每天50万左右,大小不到10M,先是把结果储存在HDFS上,然后读取转换为dataframe格式,相当于分区=文件大小/128M(block块),

则dataframe默认只有两个分区,需要通过repartition()进行重新分区,然后插入即可,如:

resDF.rdd.getNumPartitions查看该dataframe分成几个分区

resDF.repartition(11).write.mode("append").jdbc(TiDBConnect.url, tableName, prop),分成11分区,保证平均每个分区小于50000即可

 

posted @ 2019-10-31 15:32  wang_zai  阅读(1074)  评论(0)    收藏  举报