我使用LIMIT
和OFFSET
从MySql数据库中获取大量数据,如:
var offset = 0
for (s <- a to partition) {
val query = "(select * from destination LIMIT 100000 OFFSET " + offset + ") as src"
data = data.union(spark.read.jdbc(url, query, connectionProperties).rdd.map(_.mkString(","))).persist(StorageLevel.DISK_ONLY)
offset += 100000
}
val dest = data.collect.toArray
val s = spark.sparkContext.parallelize(dest, 1).persist(StorageLevel.DISK_ONLY).saveAsTextFile("/home/hduser/Desktop/testing")
对于少量数据,它的工作正常,而对于大量数据,它会抛出java.lang.OutOfMemoryError: Java heap space
之类的错误,所以如果我能坚持val dest = data.collect.toArray
它会按预期工作,抱歉这样一个天真的问题我'新来的火花。
分区方法:
val query = "(select * from destination) as dest"
val options = Map(
"url" -> "jdbc:mysql://192.168.175.35:3306/sample?useSSL=false",
"dbtable" -> query,
"user" -> "root",
"password" -> "root")
val destination = spark.read.options(options).jdbc(options("url"), options("dbtable"), "0", 1, 5, 4, new java.util.Properties()).rdd.map(_.mkString(","))
.persist(StorageLevel.DISK_ONLY).saveAsTextFile("/home/hduser/Desktop/testing")
谢谢
答案 0 :(得分:2)
我正在获取大量数据
这就是你使用Spark的原因,不是吗?:)
for (s <- a to partition)
val dest = data.collect.toArray
spark.sparkContext.parallelize(dest, 1)
注意: 请勿这样做。我甚至称它为Spark反模式,你加载一个 执行器上的数据集(来自使用JDBC的MySQL)仅用于传输它 向驾驶员发送“大量数据”,然后转移它 返回执行程序将其保存到磁盘。
就像你想要摆脱Spark进行这些网络往返一样。
spark.read.jdbc
支持在加载时使用partitionColumn
,lowerBound
,upperBound
选项(请参阅JDBC To Other Databases)或(未记录的)对数据集进行分区predicates
选项。
partitionColumn , lowerBound , upperBound 描述了在从多个工作人员并行读取时如何对表进行分区。 partitionColumn必须是相关表中的数字列。请注意,lowerBound和upperBound仅用于决定分区步幅,而不是用于过滤表中的行。因此,表中的所有行都将被分区并返回。此选项仅适用于阅读。
让Spark完成其工作。