使用 insertAll 进行流式传输时在 BigQuery 中"composite key"



我正在将数据流式传输到BigQuery表中,该表构建InsertAllRequest,然后使用com.google.cloud.bigquery.BigQuery中的insertAll-方法插入。从某种意义上说,我可以将数据插入表中,但我有一个特定的行为:我想实现某种";复合键";在表格中。

这是表格的样子:

Field name      | Type      | Mode
--------------------------------------
order_id        | STRING    | REQUIRED
modified_ts     | TIMESTAMP | REQUIRED
order_sum       | INTEGER   | NULLABLE
order_reference | STRING    | NULLABLE

所以,我希望密钥是order_idmodified_ts;换句话说,我希望能够跟踪订单随时间的变化。如果再次插入现有的键,我希望出现一些错误,或者忽略这一新行(将其视为重复行(对我来说也很好。

不幸的是,我还没有成功地告诉BigQuery这样做

String rowId = String.valueOf("order_id, modified_ts");
InsertAllRequest req = InsertAllRequest.newBuilder(ORDER)
.addRow(rowId, mapOrder(o, modifiedTs))
.build();
InsertAllResponse resp = bigQuery.insertAll(req);
log.info("response was: {}", resp.toString());

newBuilder中的ORDER是TableId-对象,mapOrder(o, modifiedTs)将传入对象映射到Map<String, Object>。如果我将rowId定义为String.valueOf("order_id"),那么一切都很好,但很明显,订单的所有更新都只是更新现有行,而不是生成任何历史记录。上面使用逗号分隔的列名的解决方案的行为与此相同,只是忽略了modified_ts

所以,我的问题很简单:我如何才能让它发挥作用?我想要的是——在某种程度上简化了——以下内容:

order_id | modified_ts | data
------------------------------------------
1    | 2020-12-10  | some data
1    | 2020-12-15  | some changed data
2    | 2020-12-15  | some more data

BigQuery中不存在复合键或UNIQUE概念。没有键和索引。

设计你的应用程序,以便插入重复项
在表的顶部创建一个视图,根据您已经布局的概念读取记录的最近一行。

通过这种方式,您也可以访问版本化的数据,并且始终可以使用查询中的view as from子句获得最新版本。

正如对Pentium 10s答案的评论所写,与谷歌代表的一次会议确认了其内容。

基本上,我误解了添加";rowId";到我的行,指示其关键字:String rowId = String.valueOf("order_id, modified_ts");这不过是谷歌所说的";尽最大努力消除重复";这只是一个最大的努力,没有任何保证。我误以为这是一种可以依靠的技巧,我的错。

建议的处理方法是在您自己的代码中,在流式传输到BigQuery之前或之后"在";这意味着在将数据写入BQ之前,在您的应用程序中实现处理重复数据的逻辑,其中包括将您识别为密钥的内容保存在内存中的某种方式"在";Pentium 10建议:将所有数据流式传输到BigQuery中并持久化,然后处理其余数据。

有3种方法可以解决这个问题";在":带有(非常方便!(窗口函数的视图可能是一种方式(但请记住,每次查询视图时都需要整个底层查询的处理能力(,物化视图可能是解决方案(如果/当谷歌支持这些窗口函数时(,或者你自己用所需数据创建和更新表,管理一些调度之王。

我希望这个答案有助于澄清问题,并作为对所提供答案的补充。

最新更新