Oracle与Spark SQL的连接



我正试图用以下代码从Spark SQL连接到Oracle数据库:

val dataTarget=sqlcontext.read.
  format("jdbc").
  option("driver", config.getString("oracledriver")).
  option("url", config.getString("jdbcUrl")).
  option("user", config.getString("usernameDH")).
  option("password", config.getString("passwordDH")).
  option("dbtable", targetQuery).
  option("partitionColumn", "ID").
  option("lowerBound", "5").
  option("upperBound", "499999").
  option("numPartitions", "10").
  load().persist(StorageLevel.DISK_ONLY)

默认情况下,当我们通过Spark SQL与Oracle连接时,它将为一个分区创建一个连接,并为整个RDD创建一个分区。这样我就失去了并行性,当表中有大量数据时就会出现性能问题。在我的代码中,我已经通过了option("numPartitions", "10")这将创建10个连接。如果我错了,请纠正,因为我知道与Oracle的连接数将等于我们通过的分区数

如果我使用更多的连接,我会得到以下错误,因为可能存在到Oracle的连接限制。

java.sql.sql异常:ORA-02391:超过同步SESSIONS_PER_USER限制

如果我使用更多的分区,为了创建更多的并行分区,会出现错误,但如果我放得更少,我将面临性能问题。有没有其他方法可以创建一个连接并将数据加载到多个分区中(这将挽救我的生命)。

请提出建议。

是否有其他方法可以创建单个连接并将数据加载到多个分区中

没有。通常,分区由不同的物理节点和不同的虚拟机处理。考虑到所有的授权和身份验证机制,您不能只获取连接并将其从一个节点传递到另一个节点。

如果问题只是超过SESSIONS_PER_USER,请联系DBA,要求增加Spark用户的值。

若问题是节流,您可以尝试保持相同数量的分区,但减少Spark内核的数量。由于这主要是微观管理,因此最好完全放弃JDBC,使用标准导出机制(COPY FROM)并直接读取文件。

一种解决方案可能是使用单个Oracle连接(分区)加载数据,然后简单地重新分区:

val dataTargetPartitioned = dataTarget.repartition(100);

您也可以通过字段进行分区(如果对数据帧进行分区):

val dataTargetPartitioned = dataTarget.repartition(100, "MY_COL");

相关内容

  • 没有找到相关文章

最新更新