我仍然是Spark的新手,但我已经能够创建Spark应用程序,我需要能够使用JDBC驱动程序从我们的SQL Server重新处理数据(我们正在删除昂贵的SP),该应用程序加载了从Sql Server通过JDBC到数据帧的几个表,然后我做了一些连接,一个组和一个过滤器,最后通过JDBC将一些数据重新插回到不同的表中。所有这些都可以在Amazon Web Services中的Spark EMR中以m3.xlarge在大约一分钟内完成,其中包含2个内核。
我的问题如下: 1.现在我在集群上有1个主服务器和2个核心,但是每次我启动一个新步骤时,从历史服务器上看到的情况看,只有1个执行程序被使用,因为我可以看到列出了2个执行程序,没有任何用法的驱动程序,一个id为1处理大约1410个任务的执行程序。而且我完全不确定如何继续。
这也是针对AWS的,但我不想发布2个问题,因为它们在某种程度上是相关的,有什么方法可以同时运行2个步骤吗?这意味着能够同时运行此进程的2个spark-submit,因为我们每天运行这个进程很多次(它处理客户端数据)。我知道我可以使用该步骤启动一个新的集群,但我希望能够快速完成处理,只需启动一个新的集群需要太长时间。 感谢!!!
答案 0 :(得分:3)
关于您的第一个问题:
我不确定是否是这种情况,但类似的事情发生在我们身上,也许它可以提供帮助。
如果使用sqlContext.read.format("jdbc").load()
(或类似)从JDBC源读取,则默认情况下,结果数据帧不会被分区。因此,如果您遇到这种情况,则在结果数据帧中应用转换而不首先对其进行分区将导致只有一个执行程序能够处理它。如果不是您的情况,以下解决方案可能无法解决您的问题。
因此,我们的解决方案是在数据中创建一个值为1到32(我们所需的分区数)的数值列,并通过设置jdbc阅读器的分区选项将其用作分区列(请检查{{ 3}}):
val connectionOptions = Map[String, String] (... <connection options> ...)
val options = connectionOptions ++ Map[String, String] (
"partitionColumn" -> "column name",
"lowerBound" -> "1",
"upperBound" -> "32",
"numPartitions" -> "32"
)
val df = sqlContext.read.format("jdbc").options(options).load()
因此,使用这种方法,不仅可以并行处理读取任务(实际上提高了性能并避免了OOM错误),而且对所有后续转换进行了分区和并行处理。
我希望有所帮助。