Spark:将大型MySQL表读入DataFrame失败

时间:2018-03-07 10:46:05

标签: mysql apache-spark

我想事先告诉我几个相关问题,如下所示,不解决我的问题:

This one接近但堆栈跟踪不同,无论如何都没有解决。所以请放心,我会在几天(失败的)解决方案之后发布这个问题。

我试图写一份工作,将数据(每天一次)从MySQL表移动到Hive表,存储为Parquet / ORC个文件Amazon S3。有些表非常大:〜300M记录 200 GB +大小(由phpMyAdmin报告)。

目前我们正在使用sqoop,但我们希望转移到Spark,原因如下:

  • 利用DataFrame API利用它的功能(将来,我们将在移动数据时执行转换
  • 我们已经在Scala中编写了 sizeable 框架,用于组织中其他地方使用的Spark个工作

我已经能够在小型 MySQL表上实现此目的而没有任何问题。但是,如果我一次尝试获取超过 ~1.5-2M记录,则Spark作业(将MySQL中的数据读入DataFrame)会失败。我已经在下方显示了堆栈跟踪的相关部分,您可以找到完整的堆栈跟踪here

...
javax.servlet.ServletException: java.util.NoSuchElementException: None.get
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:489)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
...
Caused by: java.util.NoSuchElementException: None.get
    at scala.None$.get(Option.scala:347)
    at scala.None$.get(Option.scala:345)
...
org.apache.spark.status.api.v1.OneStageResource.taskSummary(OneStageResource.scala:62)
    at sun.reflect.GeneratedMethodAccessor188.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
...
[Stage 27:>                                                       (0 + 30) / 32]18/03/01 01:29:09 WARN TaskSetManager: Lost task 3.0 in stage 27.0 (TID 92, ip-xxx-xx-xx-xxx.ap-southeast-1.compute.internal, executor 6): java.sql.SQLException: Incorrect key file for table '/rdsdbdata/tmp/#sql_14ae_5.MYI'; try to repair it
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:964)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973)
...

** 如果移动包含 186M 记录的 148 GB 表失败,则会获得此堆栈跟踪

从(完整)堆栈跟踪中可以看出,Spark读取作业以None.get SQLException: Incorrect key for file..错误后跟MySQL开始生闷 }(与MySQL' s false warnings

相关

现在显然这不是sqoop问题,因为在这种情况下Spark也会失败。就numPartitions = 32而言,我tmp table becoming full设置sqoop(我们使用40 Spark的并行度。)

来自BigDataMySQL有限知识 148 GB 不应压倒性无论如何,对于Spark来说。此外,由于SparkEMRS3)和AWS都位于同一区域AP-SouthEast Spark) ,延迟不应该是瓶颈

我的问题是:

  1. Spark是否适用于此工具?
  2. Jdbc Hadoop 驱动程序可能会因此问题受到指责吗?
  3. 如果对上述问题的回答是
    • 是的:我怎样才能克服它? (备用驱动程序或其他一些解决方法)?
    • 否:可能的原因是什么?
  4. 框架配置:

    • Spark发布:亚马逊2.8.3
    • Hive 2.2.1
    • Scala 2.3.2
    • EMR 2.11.11

    EMR配置:

    • 1 Master 5.12.0
    • 1 Task r3.xlarge [8 vCore,30.5 GiB内存,80 SSD GB存储EBS存储空间:32 GiB]
    • 1 Core r3.xlarge [8 vCore,30.5 GiB内存,80 SSD GB存储EBS存储空间:无]
    • clamp <- function(x, low, high) min(high, max(low, x)) fill1 <- function(df) { rain <- df$rain swc <- df$swc PETc <- df$PETc SW0 <- df$SW.ini[1] SW.max <- df$SW.max[1] SW <- PAW <- aetc <- numeric(nrow(df)) for (day in seq_along(rain)) { PAW[day] <- SW0 + rain[day] if (PAW[day] >= swc[day]) { aetc0 <- PETc[day] } else { aetc0 <- (PAW[day] / swc[day]) * PETc[day] } aetc[day] <- min(PAW[day], aetc0) SW0 <- SW[day] <- clamp(PAW[day] - aetc[day], 0, SW.max) } list(SW = SW, PAW = PAW, aetc = aetc) } r3.xlarge [8 vCore,30.5 GiB内存,80 SSD GB存储空间 EBS存储:32 GiB]

    ** 这些是开发集群的配置;生产集群将更好地配备

1 个答案:

答案 0 :(得分:0)

Spark JDBC API似乎是fork来将所有数据从MySQL表加载到内存而不是。因此,当您尝试加载大表时,您应该首先使用Spark API克隆数据到HDFS(JSON应该用于保持架构结构),如下所示:

spark.read.jdbc(jdbcUrl, tableName, prop)
       .write()
       .json("/fileName.json");

然后你可以正常使用HDFS。

spark.read().json("/fileName.json")
       .createOrReplaceTempView(tableName);