Google bigquery 通过在Google BigQuery上连接两个表而不导入/导出来删除/更新表项

Google bigquery 通过在Google BigQuery上连接两个表而不导入/导出来删除/更新表项,google-bigquery,Google Bigquery,我们有一个用例,在这个用例中,一个表中有数亿个条目,并且在进一步拆分它时遇到了问题。99%的操作是仅附加的。然而,我们偶尔会进行更新和删除,谷歌自己说,只有删除一个表并使用最新数据创建一个新表,才有可能进行更新和删除 由于数据量很大,我们希望在30秒左右的时间内更新表,因此我们考虑了将原始表与刷新表连接的可能性,这样我们只会在原始表中出现条目,而不会在刷新表中出现条目(删除的情况)或使用刷新表中的数据写入项目(如果发现)(更新)。输出/目标应该是新表,然后使用WRITE_TRUNCATE(覆盖)

我们有一个用例,在这个用例中,一个表中有数亿个条目,并且在进一步拆分它时遇到了问题。99%的操作是仅附加的。然而,我们偶尔会进行更新和删除,谷歌自己说,只有删除一个表并使用最新数据创建一个新表,才有可能进行更新和删除

由于数据量很大,我们希望在30秒左右的时间内更新表,因此我们考虑了将原始表刷新表连接的可能性,这样我们只会在原始表中出现条目,而不会在刷新表中出现条目(删除的情况)或使用刷新表中的数据写入项目(如果发现)(更新)。输出/目标应该是新表,然后使用WRITE_TRUNCATE(覆盖)将其复制回原始表。如果更新看起来太复杂,我们可以使用只删除逻辑,自己重新插入更新的项

这可能吗?哪种类型的连接似乎最适合?我们会将更新流式插入到刷新表中,并定期清理原始表。我们不必为重新插入整个原始表(无论是时间还是金钱)而付费,只需查询“一次”和更新表所需的少量流式插入

编辑:在定期合并发生之前,我们可以继续查询过时数据。我们还可以在维护期间短时间停止查询


欢迎有任何想法。

因此,要补充更多我的评论:


为什么不将更新作为表中的新行接受,然后 是否有只读取表中最后一行的查询?太多了 更容易

创建如下视图:

select * from (
SELECT 
rank() over (partition by user_id order by timestamp desc) as _rank,
*
FROM [db.userupdate_last] 
) where _rank=1
并更新查询以查询视图表和基本表,这样就完成了

我们是如何使用它的。我们有一个保存用户配置文件数据的事件表。每次更新时,我们都会在BQ中再次追加完整的配置文件数据行。这意味着我们最终拥有一个版本化的内容,该用户id的行数与他们所做的更新数相同。这都在同一个表中,通过查看时间,我们知道更新的顺序。假设表us:[userupdate]。如果我们做一个

select * from userupdate where user_id=10
它将以随机顺序将此用户所做的所有更新返回到其配置文件中

但是我们创建了一个视图,我们只创建了一次,语法如上所述。现在当我们:

select * from userupdate_last where user_id=10 #notice the table name changed to view name

它将只返回1行,即用户的最后一行。如果我们想从包含一堆只追加最后一行的表中进行查询,我们可以将表名交换为视图名。

我们发现,在类似的情况下,使用BigQuery有一个相对简单的选项非常有效。
它允许处理基于任何基于时间的快照的查询,以及查询当前快照

简言之,想法是拥有一个主表和每日历史表
白天-当前每日表用于插入(新建、更新、删除),然后每日进程将最后完成的每日表与主表合并,并将其写回同一主表。当然,首先,备份是通过最新主表的副本进行的(自由操作)

每日主表更新过程允许从最后一天起保持主表清洁和新鲜。
现在,在任何给定时刻,您都可以通过只查询(无垃圾)主表和只查询今天的表来获得最新数据。
同时,由于您拥有所有每日表,因此可以查询任何历史数据

当然,使用相应的限定符将所有数据(新建、更新、删除)添加到主表中的经典选项在价格和性能上看起来仍然不错,因为您的主数据(99%)是新条目

在你的情况下,我个人,我会投经典的方法定期清理历史条目


最后,在我看来,这不是关于连接,而是关于和函数的使用

为什么不接受更新作为表中的新行,并使用只读取表中最后一行的查询?那容易多了。你考虑过这个吗?这听起来像是一个我们也应该评估/基准的选项!谢谢你的精彩投入。我们必须检查哪一个对我们正在进行的查询干扰最小。我们仍然对joins如何做这项工作感兴趣。这可能是一个反连接?请注意对原始问题的编辑。我们希望保持查询的简单性,并为更新的情况支付一个小时左右的过时数据的费用。我们仍然对join方法感兴趣,因为它不会干扰现有的查询,而不会在所有读取查询上添加诸如GROUP BY userid ORDER BY version和LAST()之类的内容。我们假设与您的方法相比,这将为正常查询节省一两秒钟的时间。这是不正确的吗?因此,如果您将上述内容创建为视图,则在查询中不需要添加任何group by或order by或类似内容,只需更改表名即可。试试这个简单的步骤。我将为我们使用的hove添加更多的上下文。再次感谢,我们将对此进行评估!看起来,如果我们使用一个简单的查询,其中版本为NULL,那么我们可以以尽可能低的成本(时间和金钱)查询过时的数据-尽管您的方法非常有趣,因为它提供了对实时数据的查询!但是,删除呢?如果我们不必一直使用deleted IS NULL之类的东西进行过滤,那就太好了。像deleted IS NULL之类的过滤对BQ没有性能影响,甚至可以在视图本身中直接编译