如何使用PySpark更新Hive表中的记录?

时间:2019-03-29 13:36:37

标签: hive pyspark-sql

我们正在使用Spark处理大数据,并且最近有了新的用例,我们需要使用spark更新Hive表中的数据。

下面是一个简单的示例: 数据驻留在Hive表中,应用程序使用PySpark读入数据帧(例如df1)。 例如:数据框在下面的列中。

EmpNo名称年龄工资

1 aaaa 28 30000

2 bbbb 38 20000

3 cccc 26 25000

4 dddd 30 32000

需要使用spark将更多记录添加到表中。

例如:

动作EmpNo名称年龄工资

添加 5 dddd 30 32000

应用程序可以通过剥离“操作”列并将新数据读取到第二个数据帧(例如df2)并将其追加到表中。简单明了,效果很好。

df.write.format('parquet')\             .mode('append')\             .saveAsTable(canonical_hive_table)

在某些情况下,我们需要根据“操作”列删除现有记录或进行更新。

例如:

动作EmpNo名称年龄工资

删除 2 bbbb 38 20000

更新 4 dddd 30 42000

在上面的示例中,应用程序需要删除EmpNo:2并更新EmpNo:4。

最终输出应如下所示:

EmpNo名称年龄工资

1 aaaa 28 30000

3 cccc 26 25000

4 dddd 30 42000

5 dddd 30 32000

据我了解,Spark Sql中不提供更新操作,而且数据帧是不可变的,无法更改记录。

有人遇到这种情况吗?还是知道使用PySpark更新Hive表中现有记录的任何选项?

Pls:应用程序需要定期处理数百万条记录上的数千个更新。

谢谢。

1 个答案:

答案 0 :(得分:0)

在大多数情况下,您需要使用正确的工具和方法-并意识到任何局限性; Hadoop基本上是一成不变的。

数据帧可以以不同的模式保存,但不能选择性地更新记录-pyspark或scala或R或JAVA与它无关,但Cloudera的KUDU Storage Manager除外,该管理器具有DF Writer可以使用的Spark连接器,但是,当我上次使用此功能时,管理员并不喜欢它的安全性限制。

你能做什么?

  1. 使用易变的 KUDU -但我怀疑这不是一种选择。就像PARQUET-圆柱状,其表现与我的经验相当。
  2. 是否使用DF,并使用 ORC 文件而不是PARQUET来保持持久性,这些文件也是列状的,可以在脚本中使用Hive的MERGE语句或启用Hive支持的Spark SQL进行更新。此选项意味着忘记PARQUET。该链接提供了一些有趣的见解:https://www.quora.com/What-are-the-differences-between-ORC-Avro-and-Parquet-File-Formats-in-Hadoop-in-terms-of-compression-and-speed
  3. 在DF上做什么,什么不做,重新声明(即再次写入)所有数据,并再次写入PARQUET表/目录的两个版本中的一个,不论是否分区,以及添加视图层以在当前视图和新版本视图之间切换。当不使用ORC时完成此操作。

使用MERGE,可以压缩分区中的小型Hadoop Hive文件,但前提是格式为ORC(如果内存正确使用)。我将不得不在这里刷新我的记忆,可能是它已在较新的版本和API中更改。

此外:

  1. 因此,您有一些选择,而不必使用DF在SPARK中全部完成。
  2. Databricks也有用于此类物品的DELTA表。
  3. 如果使用RDBMS.s的JDBC导入,则可以以尴尬的方式将sqoop与外部表一起使用以获取更新的数据,但是我不能从问题中看出这一点。逻辑如下:sqoop merge-key creating multiple part files instead of one which doesn't serve the purpose of using merge-key

需要考虑的几件事。祝你好运。