Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Scala更新Spark中数据库中的数据_Scala_Apache Spark - Fatal编程技术网

使用Scala更新Spark中数据库中的数据

使用Scala更新Spark中数据库中的数据,scala,apache-spark,Scala,Apache Spark,我正在与spark和scala合作一个项目,我对这两个项目都不熟悉,但在stackoverflow的帮助下,我完成了所有数据处理,并将处理后的数据存储在mysql中。现在我终于面临一个问题,我不知道如何解决它。第一次处理数据时,我使用此方法存储数据帧,并且第一个时间表为空 df.write.mode("append").jdbc("dburl", "tablename", "dbproperties"); 假设我处理的数据在数据库中是这样的 id name

我正在与spark和scala合作一个项目,我对这两个项目都不熟悉,但在stackoverflow的帮助下,我完成了所有数据处理,并将处理后的数据存储在mysql中。现在我终于面临一个问题,我不知道如何解决它。第一次处理数据时,我使用此方法存储数据帧,并且第一个时间表为空

      df.write.mode("append").jdbc("dburl", "tablename", "dbproperties"); 
假设我处理的数据在数据库中是这样的

      id      name       eid      number_of_visitis    last_visit_date
      1       John       C110     12                   2016-01-13 00:00:00
      2       Root       C111     24                   2016-04-27 00:00:00
      3       Michel     C112     8                    2016-07-123 00:00:00
      4       Jonny      C113     45                   2016-06-10 00:00:00
现在,具有eid“C111”的名为“Root”的人员在“2016-08-30 00:00:00”访问办公室2次。现在,处理完此新数据后,我只需要更新数据库中的此人员记录。我将如何做到这一点。现在更新的表应该是这样的

      id      name       eid      number_of_visitis    last_visit_date
      1       John       C110     12                   2016-01-13 00:00:00
      2       Root       C111     26                   2016-08-30  00:00:00
      3       Michel     C112     8                    2016-07-123 00:00:00
      4       Jonny      C113     45                   2016-06-10 00:00:00
此表中有数百万数据,如果我在spark dataframe中加载完整表并更新所需记录,则需要更多时间,而且这也没有意义,因为为什么我只想更新一行时加载完整表。我尝试了此代码,但它将新行添加到表中,而不是更新行

       df.write.mode("append").jdbc("dburl", "tablename", "dbproperties");
在spark有什么方法可以做到这一点吗

我在网上看到过这个,我可以这样做来更新吗

val numParallelInserts = 10
val batchSize = 1000

new CoalescedRDD(sessions, numParallelInserts) mapPartitionsWithSplit { (split, iter) => Iterator((split, iter)) } foreach { case (split, iter) =>
  val db = connect()

  val sql = "INSERT INTO sessions (id, ts) VALUES (?, ?)"
  val stmt = db.prepareStatement(sql)

  iter.grouped(batchSize).zipWithIndex foreach { case (batch, batchIndex) =>
    batch foreach { session =>
      stmt.setString(1, session.id)
      stmt.setString(2, TimestampFormat.print(session.ts))
      stmt.addBatch()
    }
    stmt.executeBatch()
    db.commit();
    logInfo("Split " + (split+1) + "/" + numParallelInserts + " inserted batch " + batchIndex + " with " + batch.size + " elements")
  }

  db.close();

您可以尝试使用sql来实现这一点。将更新的(甚至是新的)数据存储在新的临时表中,然后将临时表合并到主表中

一种方法是:

  • 使用临时表更新主表中的所有记录

    更新主表
    设置访问次数=主表访问次数+临时表访问次数
    从临时表
    其中main_table.eid=temp_table.eid

  • 从临时表中删除所有重复记录(即在临时表中只保留新记录)

    从temp_表中删除,其中main_table.eid=temp_table.eid

  • 将临时表中的所有记录插入主表

    插入主表,从临时表中选择*

  • 放下临时桌子

    drop table temp_table


  • 您是否尝试过“覆盖”模式?覆盖使用不精确的数据类型重新创建表,删除所有旧数据,只插入新处理的数据。这是在数据库级别,有更多步骤,我希望以最短的方式完成。我有数以百万计的数据,所以复制、删除和插入都需要时间。我更新了这个问题,请看一下,也许你能理解我想做什么。我在一个有几十亿行的红移数据库上使用这个问题。