转自:https://blog.csdn.net/lsshlsw/article/details/49789373

很多人在spark中使用默认提供的jdbc方法时,在数据库数据较大时经常发现任务 hang 住,其实是单线程任务过重导致,这时候需要提高读取的并发度。 
下文以 mysql 为例进行说明。

在spark中使用jdbc

在 spark-env.sh 文件中加入:

export SPARK_CLASSPATH=/path/mysql-connector-java-5.1.34.jar

任务提交时加入:

--jars /path/mysql-connector-java-5.1.34.jar

1. 单partition(无并发)

调用函数

def jdbc(url: String, table: String, properties: Properties): DataFrame

使用:

val url = "jdbc:mysql://mysqlHost:3306/database"
val tableName = "table" // 设置连接用户&密码
val prop = new java.util.Properties
prop.setProperty("user","username")
prop.setProperty("password","pwd") // 取得该表数据
val jdbcDF = sqlContext.read.jdbc(url,tableName,prop) // 一些操作
....

查看并发度

jdbcDF.rdd.partitions.size # 结果返回 1

该操作的并发度为1,你所有的数据都会在一个partition中进行操作,意味着无论你给的资源有多少,只有一个task会执行任务,执行效率可想而之,并且在稍微大点的表中进行操作分分钟就会OOM。

更直观的说法是,达到千万级别的表就不要使用该操作,count操作就要等一万年,no zuo no die ,don’t to try !

WARN TaskSetManager: Lost task 0.0 in stage 6.0 (TID 56, spark047219):
java.lang.OutOfMemoryError: GC overhead limit exceeded
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3380)

2. 根据Long类型字段分区

调用函数

  def jdbc(
url: String,
table: String,
columnName: String, # 根据该字段分区,需要为整形,比如id等
lowerBound: Long, # 分区的下界
upperBound: Long, # 分区的上界
numPartitions: Int, # 分区的个数
connectionProperties: Properties): DataFrame

使用:

val url = "jdbc:mysql://mysqlHost:3306/database"
val tableName = "table" val columnName = "colName"
val lowerBound = 1,
val upperBound = 10000000,
val numPartitions = 10, // 设置连接用户&密码
val prop = new java.util.Properties
prop.setProperty("user","username")
prop.setProperty("password","pwd") // 取得该表数据
val jdbcDF = sqlContext.read.jdbc(url,tableName,columnName,lowerBound,upperBound,numPartitions,prop) // 一些操作
....

查看并发度

jdbcDF.rdd.partitions.size # 结果返回 10

该操作将字段 colName 中1-10000000条数据分到10个partition中,使用很方便,缺点也很明显,只能使用整形数据字段作为分区关键字。

3000w数据的表 count 跨集群操作只要2s。

3. 根据任意类型字段分区

调用函数

jdbc(
url: String,
table: String,
predicates: Array[String],
connectionProperties: Properties): DataFrame

下面以使用最多的时间字段分区为例:

val url = "jdbc:mysql://mysqlHost:3306/database"
val tableName = "table" // 设置连接用户&密码
val prop = new java.util.Properties
prop.setProperty("user","username")
prop.setProperty("password","pwd") /**
* 将9月16-12月15三个月的数据取出,按时间分为6个partition
* 为了减少事例代码,这里的时间都是写死的
* modified_time 为时间字段
*/ val predicates =
Array(
"2015-09-16" -> "2015-09-30",
"2015-10-01" -> "2015-10-15",
"2015-10-16" -> "2015-10-31",
"2015-11-01" -> "2015-11-14",
"2015-11-15" -> "2015-11-30",
"2015-12-01" -> "2015-12-15"
).map {
case (start, end) =>
s"cast(modified_time as date) >= date '$start' " + s"AND cast(modified_time as date) <= date '$end'"
} // 取得该表数据
val jdbcDF = sqlContext.read.jdbc(url,tableName,predicates,prop) // 一些操作

查看并发度

jdbcDF.rdd.partitions.size # 结果返回 6

该操作的每个分区数据都由该段时间的分区组成,这种方式适合各种场景,较为推荐。

结语

以 mysql 3000W 数据量表为例,单分区count,僵死若干分钟报OOM。

分成5-20个分区后,count 操作只需要 2s

高并发度可以大幅度提高读取以及处理数据的速度,但是如果设置过高(大量的partition同时读取)也可能会将数据源数据库弄挂。

spark jdbc(mysql) 读取并发度优化的更多相关文章

  1. JSP + JDBC + MySQL 读取数据库内容到网页

    创建数据库表 导入JDCB驱动 mysql.jsp <%@ page language="java" %> <%@ page contentType=" ...

  2. 如何处理PHP和MYSQL的并发以及优化

    sql优化,数据缓存和页面静态化首先各种优化程序逻辑优化数据库优化硬件横向扩展数据hash.服务器提升性能.表hash.出钱找oraclec出解决方案页面静态化:Php页面静态化有两种,第一,php模 ...

  3. Tomcat + Mysql高并发配置优化

    1.Tomcat优化配置 (1)更改Tomcat的catalina.bat 将java变成server模式,增大jvm的内存,在文件开始位置增加 setJAVA_OPTS=-server -Xms10 ...

  4. 使用Apache Spark 对 mysql 调优 查询速度提升10倍以上

    在这篇文章中我们将讨论如何利用 Apache Spark 来提升 MySQL 的查询性能. 介绍 在我的前一篇文章Apache Spark with MySQL 中介绍了如何利用 Apache Spa ...

  5. Spark JDBC系列--取数的四种方式

    Spark JDBC系列--取数的四种方式 一.单分区模式 二.指定Long型column字段的分区模式 三.高自由度的分区模式 四.自定义option参数模式 五.JDBC To Other Dat ...

  6. Spark JDBC To MySQL

    mysql jdbc driver下载地址https://dev.mysql.com/downloads/connector/j/ 在spark中使用jdbc1.在 spark-env.sh 文件中加 ...

  7. spark练习--mysql的读取

    前面我们一直操作的是,通过一个文件来读取数据,这个里面不涉及数据相关的只是,今天我们来介绍一下spark操作中存放与读取 1.首先我们先介绍的是把数据存放进入mysql中,今天介绍的这个例子是我们前两 ...

  8. Spark使用Java读取mysql数据和保存数据到mysql

    原文引自:http://blog.csdn.net/fengzhimohan/article/details/78471952 项目应用需要利用Spark读取mysql数据进行数据分析,然后将分析结果 ...

  9. Spark JDBC方式连接MySQL数据库

    Spark JDBC方式连接MySQL数据库 一.JDBC connection properties(属性名称和含义) 二.spark jdbc read MySQL 三.jdbc(url: Str ...

随机推荐

  1. jQuery必知必会

    原文地址:https://my.oschina.net/u/218421/blog/37391 jQuery优势 轻量级    强大的选择器   出色的DOM操作的封装   可靠的事件处理机制   完 ...

  2. IO流一些问题的总结

    字节流的继承体系 字符流的继承体系 字符编码是什么?常见的字符编码表有哪些? 字符编码(英语:Character encoding)也称字集码,是把字符集中的字符编码为指定集合中某一对象,以便文本在计 ...

  3. SpringBoot 基础(二)

    目录 SpringBoot基础(二) 一.操作数据库 1. SpringBootJdbc 2. SpringBoot 整合 Mybatis 3. SpringBott 使用JPA 二.使用 Thyme ...

  4. C语言输入带空格的字符串

    参考:https://blog.csdn.net/vincemar/article/details/78750435 因为: scanf("%s",str); 遇到空格就停止接收后 ...

  5. 复习:C语言基础知识1

    占位符: %d, %i,代表整数,%f-浮点,%s,字符串,%c,char. %p 指针,%fL 长long,%e科学计数,%g 小数或科学计数. C语言中的格式占位符: %a,%A 读入一个浮点值( ...

  6. Akka-CQRS(13)- SSL/TLS for gRPC and HTTPS:自签名证书产生和使用

    到现在,我们已经完成了POS平台和前端的网络集成.不过,还是那句话:平台系统的网络安全是至关重要的.前一篇博客里我们尝试实现了gRPC ssl/tls网络连接,但测试时用的证书如何产生始终没有搞清楚. ...

  7. Marshmallow详解

    目录 Marshmallow详解 1. Scheme 2. Serializing(序列化) 3. 过滤输出 4. Deserializing(反序列化) 5. 处理多个对象的集合 6. Valida ...

  8. DRF的APIView、GenericAPIView、GenericViewSet的原理分析

    一.层次结构 GenericViewSet(ViewSetMixin, generics.GenericAPIView) ---DRF GenericAPIView(views.APIView) -- ...

  9. 原生js数值开根算法

    不借助Math函数求开根值 1.二分迭代法求n开根后的值 思路: left=0 right=n mid=(left+right)/2 比较mid^2与n大小 =输出: >改变范围,right=m ...

  10. 服务器推送之SSE简单使用

    前端 <!DOCTYPE html> <html> <head> <meta name="viewport" content=" ...