与Spark SQL的Oracle连接

时间:2017-10-12 11:54:32

标签: oracle apache-spark database-connection apache-spark-sql

我正在尝试使用以下代码从Spark SQL连接到Oracle DB:

 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.SQLException:ORA-02391:超出了同步时间   SESSIONS_PER_USER限制

如果我使用更多分区,为并行性创建更多分区,则会出现错误,但如果我放少了,则会遇到性能问题。有没有其他方法来创建单个连接并将数据加载到多个分区(这将节省我的生命)。

请建议。

2 个答案:

答案 0 :(得分:1)

  

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

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

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

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

答案 1 :(得分:0)

一种解决方法可能是使用单个Oracle连接(分区)加载数据,然后只需Here

val dataTargetPartitioned = dataTarget.repartition(100);

您还可以按字段进行分区(如果repartition):

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