Dataframe 通过pyspark作业更新数据库表的最佳方法

Dataframe 通过pyspark作业更新数据库表的最佳方法,dataframe,apache-spark,pyspark,google-bigquery,bigdata,Dataframe,Apache Spark,Pyspark,Google Bigquery,Bigdata,我有一个spark工作,它从多个源获取数据,并将数据聚合到一个表中。只有在有新数据时,作业才应更新表 我可以想到的一种方法是从现有的表中获取数据,并与传入的新数据进行比较。比较发生在火花层 我想知道是否有更好的比较方法,可以提高比较性能 如果有人对此有建议,请告诉我 非常感谢 数据库中是否应该有上次更新时间?您使用的方法听起来不可伸缩,因此如果您有办法为表中的每一行设置更新时间,它将解决问题 我可以想到的一种方法是从现有数据库中获取数据 表,并与输入的新数据进行比较 不执行与加载新数据比较的所有

我有一个spark工作,它从多个源获取数据,并将数据聚合到一个表中。只有在有新数据时,作业才应更新表

我可以想到的一种方法是从现有的表中获取数据,并与传入的新数据进行比较。比较发生在火花层

我想知道是否有更好的比较方法,可以提高比较性能

如果有人对此有建议,请告诉我


非常感谢

数据库中是否应该有上次更新时间?您使用的方法听起来不可伸缩,因此如果您有办法为表中的每一行设置更新时间,它将解决问题

我可以想到的一种方法是从现有数据库中获取数据 表,并与输入的新数据进行比较

不执行与加载新数据比较的所有数据

备选案文1:

相反,您可以创建分区表并创建一个分区列来加载数据,并且在加载新数据时,您还可以检查新数据是否具有相同的分区列。 在hive或bigquery中命中分区级数据比在spark中选择整个数据并进行比较更有用/更高效

这同样适用于蜂巢

看到这个了吗 或

备选案文2:

另一种选择是使用we have merge语句,如果您的要求是在不进行比较的情况下合并数据,那么您可以继续使用merge语句。。请参阅下面的文档链接


使用这一点,我们可以提高性能,因为插入、更新和删除这三个操作都是一次性执行的。我们不需要编写单独的语句来更新目标表中的更改。

解决此问题的方法有很多,其中一种成本更低、性能更好、可扩展的方法是使用文件系统上的数据存储来确定真正的新数据

当数据第一次进入时,将其写入两个位置-数据库和文件(如s3中的文件)。如果数据库中已有数据,则需要使用表数据初始化本地/s3文件。 当数据在第二次之后出现时,根据本地/s3文件检查它是否是新的。 将增量数据标记为新数据或已更新数据。将其作为插入或更新导出到数据库。 随着时间的推移,这个文件会越来越大。定义更新数据不会超过的日期范围。定期截断此文件以将数据保持在该时间范围内。 您还可以对这些数据进行bucket和分区。您也可以使用deltalake来维护它

一个缺点是,无论何时更新数据库,都可能需要根据相关数据是否发生更改来更新此文件。您可以在数据库表上维护一个标记来表示同步日期。也为该列编制索引。根据此列读取已更改的记录,并更新文件/deltalake


这样,您的sparl应用程序将更少地依赖于数据库。数据库操作的可扩展性不是很强,因此最好让它们远离关键路径

谢谢你,Ilya。读取到spark作业中的新数据来自多个来源。没有时间戳。我可以在我正在创建的表中添加更新时间戳,但是我仍然需要读取数据并进行比较。正当例如,作业可以运行,但仍然可以看到昨天看到的相同数据。如果我误解了你的建议,请纠正我。嗨,如果你没有时间戳数据。。。。您可以使用任意对象作为分区列来查询数据。读取分区比较优于读取整个数据进行比较。请看我的回答谢谢你,拉姆。即使我按时间戳对表进行分区,我也会遇到同样的问题,对吗?例如,我今天创建表,并使用今天的数据更新表。当作业明天运行时,如果它是相同的数据,那么数据不会仍然复制到表中,除非它将位于不同的分区中。如果我的理解不正确,请纠正我。谢谢可能不是基于时间戳的分区,例如类别。通过检查类别项(如果不存在),可以加载数据。。。否则,您可以忽略新数据。。。像这样的东西。。。。通过这样做,基本上您并不是将所有类别的所有数据与新类别进行比较。您将仅通过不将所有数据加载到spark内存中进行比较来比较单个类别项单个分区列。非常感谢,Ram。让我试试这个主意如果您还好,请作为所有者接受答案。感谢您还可以将新数据写入临时表,然后使用Bigquery更新目标表。答案将基于意见。请检查一下我在我的项目中做了什么