使用Scala更新Spark中数据库中的数据
我正在与spark和scala合作一个项目,我对这两个项目都不熟悉,但在stackoverflow的帮助下,我完成了所有数据处理,并将处理后的数据存储在mysql中。现在我终于面临一个问题,我不知道如何解决它。第一次处理数据时,我使用此方法存储数据帧,并且第一个时间表为空使用Scala更新Spark中数据库中的数据,scala,apache-spark,Scala,Apache Spark,我正在与spark和scala合作一个项目,我对这两个项目都不熟悉,但在stackoverflow的帮助下,我完成了所有数据处理,并将处理后的数据存储在mysql中。现在我终于面临一个问题,我不知道如何解决它。第一次处理数据时,我使用此方法存储数据帧,并且第一个时间表为空 df.write.mode("append").jdbc("dburl", "tablename", "dbproperties"); 假设我处理的数据在数据库中是这样的 id name
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代码>
您是否尝试过“覆盖”模式?覆盖使用不精确的数据类型重新创建表,删除所有旧数据,只插入新处理的数据。这是在数据库级别,有更多步骤,我希望以最短的方式完成。我有数以百万计的数据,所以复制、删除和插入都需要时间。我更新了这个问题,请看一下,也许你能理解我想做什么。我在一个有几十亿行的红移数据库上使用这个问题。