Spark SQL和MySQL-SaveMode.Overwrite不插入修改后的数据

时间:2017-01-26 12:30:12

标签: mysql apache-spark dataframe apache-spark-sql

我在MySQL中有一个test表,其ID和名称如下所示:

+----+-------+
| id | name  |
+----+-------+
| 1  | Name1 |
+----+-------+
| 2  | Name2 |
+----+-------+
| 3  | Name3 |
+----+-------+

我使用Spark DataFrame来读取这些数据(使用JDBC)并修改这样的数据

Dataset<Row> modified = sparkSession.sql("select id, concat(name,' - new') as name from test");
modified.write().mode("overwrite").jdbc(AppProperties.MYSQL_CONNECTION_URL,
                "test", connectionProperties);

但我的问题是,如果我提供覆盖模式,它会丢弃上一个表并创建一个新表但不插入任何数据。

我通过读取csv文件(与测试表相同的数据)和覆盖来尝试相同的程序。这对我有用。

我在这里遗漏了什么吗?

谢谢!

3 个答案:

答案 0 :(得分:8)

问题在于您的代码。因为您覆盖了一个您尝试读取的表,所以在Spark实际访问之前,您会有效地删除所有数据。

请记住,Spark是懒惰的。创建Dataset Spark时,会获取所需的元数据,但不会加载数据。因此,没有魔法缓存可以保留原始内容。实际需要时将加载数据。这是当你执行write动作时,当你开始写作时,没有更多的数据可以被提取。

你需要的是这样的东西:

  • 创建Dataset
  • 应用所需的转换并将数据写入中间MySQL表。

  • TRUNCATE来自中间表的原始输入和INSERT INTO ... SELECTDROP原始表和RENAME中间表。

替代但不太有利的方法是:

  • 创建Dataset
  • 应用所需的转换并将数据写入持久性Spark表(df.write.saveAsTable(...)或等效的)
  • TRUNCATE原始输入。
  • 重新读取数据并保存(spark.table(...).write.jdbc(...)
  • Drop Spark table。

我们不能强调使用Spark cache / persist是不可能的。即使使用保守的StorageLevelMEMORY_AND_DISK_2 / MEMORY_AND_DISK_SER_2),缓存的数据也可能会丢失(节点失败),从而导致无声的正确性错误。

答案 1 :(得分:1)

我认为上述所有步骤都是不必要的。这是您需要做的:

  • 创建数据集A,例如val A = spark.read.parquet("....")

  • 以数据帧B的形式读取要更新的表。确保为数据帧B启用了启用缓存。 val B = spark.read.jdbc("mytable").cache

  • count上强制使用B-这将强制执行并根据所选的StorageLevel-B.count

  • 缓存表>
  • 现在,您可以进行类似val C = A.union(B)

  • 的转换
  • 然后,将CC.write.mode(SaveMode.Overwrite).jdbc("mytable")

  • 一样写回到数据库

答案 2 :(得分:0)

读取和写入同一张表。

cols_df = df_2.columns

broad_cast_var = spark_context.broadcast(df_2.collect())

df_3 = sqlContext.createDataFrame(broad_cast_var.value, cols_df)

在相同的表上进行读写操作。

cols_df = df_2.columns

broad_cast_var = spark_context.broadcast(df_2.collect())


def update_x(x):
    y = (x[0] + 311, *x[1:])
    return y


rdd_2_1 = spark_context.parallelize(broad_cast_var.value).map(update_x)

df_3 = sqlContext.createDataFrame(rdd_2_1, cols_df)