Spark使用jdbc时的并行度
Spark SQL支持数据源使用JDBC从其他数据库读取数据。 与使用JdbcRDD相比,应优先使用此功能。 这是因为结果以DataFrame的形式返回,并且可以轻松地在Spark SQL中进行处理或与其他数据源合并。 JDBC数据源也更易于从Java或Python使用,因为它不需要用户提供ClassTag。 (请注意,这与Spark SQL JDBC服务器不同,后者允许其他应用程序使用Spark SQL运行查询)。
首先,您需要在spark类路径上包含特定数据库的JDBC驱动程序。
例如,要从Spark Shell连接到postgres,您可以运行以下命令:
bin/spark-shell --driver-class-path postgresql-9.4.1207.jar --jars postgresql-9.4.1207.jar
- Spark读取关系型数据库,官方有API接口,如下:
①、SparkSession.read.jdbc(url, table, properties)
②、SparkSession.read.jdbc(url, table, columnName, lowerBound, upperBound, numPartitions, connectionProperties)
③、SparkSession.read.jdbc(url, table, predicates, connectionProperties)
- 单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 = spark.read.jdbc(url,tableName,prop)
// 一些操作
jdbcDF.write.mode..
查看并发度
jdbcDF.rdd.partitions.size # 结果返回 1
该操作的并发度为1,你所有的数据都会在一个partition中进行操作,意味着无论你给的资源有多少,只有一个task会执行任务,执行效率可想而之,并且在稍微大点的表中进行操作分分钟就会OOM。
更直观的说法是,达到千万级别的表就不要使用该操作,count操作就要等一万年,亲测4个小时 !
- 根据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 = spark.read.jdbc(url,tableName,columnName,lowerBound,upperBound,numPartitions,prop)
// 一些操作
....
查看并发度
jdbcDF.rdd.partitions.size # 结果返回 10
该操作将字段 colName 中1-10000000条数据分到10个partition中,使用很方便,缺点也很明显,只能使用整形数据字段作为分区关键字。
- 根据任意类型字段分区
调用函数为
jdbc(
url: String,
table: String,
predicates: Array[String],
connectionProperties: Properties): DataFrame
例子:
val url = "jdbc:mysql://localhost:3306/db"
val tableName = "tablename"
// 设置连接用户&密码
val prop = new java.util.Properties
prop.setProperty("user","mysql")
prop.setProperty("password","123456")
val predicates =
Array(
"2018-10-01" -> "2018-11-01",
"2018-11-02" -> "2018-12-01",
"2018-12-02" -> "2019-01-01",
"2019-02-02" -> "2019-03-01",
"2019-03-02" -> "2019-04-01",
"2019-04-02" -> "2019-05-01",
"2019-05-02" -> "2019-06-01",
"2019-06-02" -> "2019-07-01",
"2019-07-02" -> "2019-08-01",
"2019-08-02" -> "2019-09-01",
"2019-09-02" -> "2019-10-01",
"2019-10-02" -> "2019-11-01"
).map {
case (start, end) =>
s"cast(txntime as date) >= date '$start' " + s"AND cast(txntime as date) <= date '$end'"
}
// 取得该表数据
val jdbcDF = spark.read.jdbc(url, tableName, predicates, prop)
// 写入到hive表
jdbcDF.write.partitionBy().mode("overwrite").format("orc")
.saveAsTable("db.tableName")
一千万级别数据实测2.4min左右导入完成。
limit分页分区
依旧采用上述函数,但是partitions做了修改,例子:
val url = "jdbc:mysql://localhost:3306/db"
val tableName = "tablename"
// 设置连接用户&密码
val prop = new java.util.Properties
prop.setProperty("user","mysql")
prop.setProperty("password","123456")
def getPartition(count:Int) = {
val step = count / 10
Range(0, count, step).map(x =>{
(x, step)
}).toArray
}
val partitions = getPartition(10000000)
.map {
case (start,end) => s"1=1 limit ${start},${end}"
}
// 取得该表数据
val jdbcDF = spark.read.jdbc(url, tableName, partitions, prop)
// 写入到hive表
jdbcDF.write.partitionBy().mode("overwrite").format("orc")
.saveAsTable("db.tableName")
实际测试效果和上面的差不多,区别是这里不需要字段有特殊的要求,对行数做处理就行啦。
Spark使用jdbc时的并行度的更多相关文章
- spark之JDBC开发(实战)
一.概述 Spark Core.Spark-SQL与Spark-Streaming都是相同的,编写好之后打成jar包使用spark-submit命令提交到集群运行应用$SPARK_HOME/bin#. ...
- spark之JDBC开发(连接数据库测试)
spark之JDBC开发(连接数据库测试) 以下操作属于本地模式操作: 1.在Eclipse4.5中建立工程RDDToJDBC,并创建一个文件夹lib用于放置第三方驱动包 [hadoop@CloudD ...
- 使用Spring Boot操作Hive JDBC时,启动时报出错误:NoSuchMethodError: org.eclipse.jetty.servlet.ServletMapping.setDef
使用Spring Boot操作Hive JDBC时,启动时报出错误:NoSuchMethodError: org.eclipse.jetty.servlet.ServletMapping.setDef ...
- spark通过JDBC读取外部数据库,过滤数据
官网链接: http://spark.apache.org/docs/latest/sql-programming-guide.html#jdbc-to-other-databases http:// ...
- streaming优化:spark.default.parallelism调整处理并行度
官方是这么说的: Cluster resources can be under-utilized if the number of parallel tasks used in any stage o ...
- spark 操作Hive时遇到的问题
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).17/10/14 ...
- Spark读写HBase时出现的问题--RpcRetryingCaller: Call exception
问题描述 Exception in thread "main" org.apache.hadoop.hbase.client.RetriesExhaustedException: ...
- Spark实际项目中调节并行度
实际项目中调节并行度 实际项目中调节并行度 并行度概述 spark架构一览 如果不调节并行度,导致并行度过低,会怎么样? 设置spark作业并行度 小结 并行度概述 其实就是指的是,Spark作业中, ...
- Spark执行失败时的一个错误分析
错误分析 堆栈信息中有一个错误信息:Job aborted due to stage failure: Task 1 in stage 2.0 failed 4 times, most recent ...
随机推荐
- linux入门系列16--文件共享之Samba和NFS
前一篇文章"linux入门系列15--文件传输之vsftp服务"讲解了文件传输,本篇继续讲解文件共享相关知识. 文件共享在生活和工作中非常常见,比如同一团队中不同成员需要共同维护同 ...
- 由一个项目需求引发的 - textarea中的换行和空格
当我们使用 textarea 在前台编辑文字,并用 js 提交到后台的时候,空格和换行是我们最需要考虑的问题.在textarea 里面,空格和换行会被保存为/s和/n,如果我们前台输入和前台显示的文字 ...
- springboot1.5.9整合websocket实现实时显示的小demo
最近由于项目需要实时显示数据库更新的数据变化情况,一开始想过在前端使用ajax异步轮询方法实现,但后面考虑到性能和流量等要求,就放弃该方法而选择使用websocket(毕竟现在springboot整合 ...
- CORS(cross-origin-resource-sharing)跨源资源共享
其实就是跨域请求.我们知道XHR只能访问同一个域中的资源,这是浏览器的安全策略所限制,但是开发中合理的跨域请求是必须的.CORS是W3的一个工作草案,基本思想就是:使用自定义的HTTP头部让浏览器与服 ...
- R语言实战(二) 创建数据集
2.1 数据集的概念 不同的行业对于数据集的行和列叫法不同.统计学家称它们为观测(observation)和变量(variable),数据库分析师则称其为记录(record)和字段(field),数据 ...
- burpsuit之Spider、Scanner、Intruder模块
1.spider模块 1.spider模块介绍 被动爬网:(被动爬网获得的链接是手动爬网的时候返回页面的信息中分析发现超链接) 对于爬网的时候遇到HTML表单如何操作: 需要表单身份认证时如何操作(默 ...
- 3分钟入门lambda表达式
本节是lambda表达式的一个入门课,讲解的同时配有练习demo 前言什么是lambda表达式?基础语法函数式接口自己实现一个函数式接口jdk提供的函数式接口Consumersupplierfunct ...
- Anaconda3环境下安装OpenCV(cv2)
Anaconda3环境下安装OpenCV(cv2) 主要步骤 1 首先查看自己的Anaconda安装的python版本 2 下载相应的OpenCv.whl文件 3 使用cmd安装.whl文件 查看自己 ...
- Mysql优化大分页查询
如题,年前做了一个需求,涉及到Mysql大分页查询,整理一下,希望对需要的小伙伴有帮助. 背景分页查询的性能瓶颈B+树简述B+比起二叉查找树,有什么优势?分页查询过程测试集解决方法1 延迟关联法:2 ...
- java-打印流(新手)
实例:1.直接输出到文件里面. import java.io.*; //打印流->保持数据原样性并且打印.(各种数据类型.) public class Dyl { public static v ...