【问题标题】:Google BigQuery There are no primary key or unique constraints, how do you prevent duplicated records being inserted?Google BigQuery 没有主键或唯一约束,如何防止插入重复记录?
【发布时间】:2017-08-13 19:13:04
【问题描述】:

Google BigQuery 没有主键或唯一约束。

我们不能使用传统的 SQL 选项,例如 insert ignoreinsert on duplicate key update,那么如何防止重复记录被插入到 Google BigQuery 中?

如果我必须先调用 delete(基于我自己系统中的唯一键)然后插入以防止将重复记录插入 bigquery,那会不会太低效?我会假设插入是最便宜的操作,没有查询,只是追加数据。对于每个插入,如果我必须调用 delete,这将太低效并且花费我们额外的钱。

根据您的经验,您有什么建议和建议?

bigquery 有主键就好了,但它可能与 bigquery 所基于的算法/数据结构冲突?

【问题讨论】:

  • 你在直播吗?流式处理根据您提供的 id 在时间范围内防止重复记录
  • 我不熟悉 bigquery 上的流式传输。我们在 bigquery 中设置传输以从 Youtube 报告中提取数据。有时传输没有得到我们想要的报表数据(可能数据还没有准备好)。我们必须重新运行传输以提取丢失的报告。谷歌告诉我们,即使我们重新运行转账,也不会出现重复记录。是使用流式传输的 bigquery 传输吗?重复的来自本地数据库。我也需要将本地 mysql 数据库中的数据加载到 bigquery 中。我必须在应用程序级别阻止它。我会看看流媒体解决方案。

标签: google-bigquery


【解决方案1】:

所以让我们首先澄清一些事实。

Bigquery 是适用于大型数据集的托管数据仓库,它是对传统数据库的补充,而不是替代

直到 2020 年初,每天最多只能对一个表执行 96 次 DML(更新、删除)操作。这种低限制迫使您将 BQ 视为数据湖。该限制有been removed,但它表明系统的早期设计是围绕“仅附加”。

因此,在 BigQuery 上,您实际上是让所有数据进入,并支持仅追加设计。这意味着根据设计,您有一个数据库,每次更新都会保存一个新行。因此,如果你想使用最新的数据,你需要选择最后一行并使用它。

我们实际上利用了我们添加到同一行的每个新更新的见解。例如,我们可以检测最终用户在注册流程中选择他/她的国家需要多长时间。因为我们有一个国家下拉列表,所以他/她滚动到正确的国家需要一些时间,并且指标显示了这一点,因为我们最终在 BQ 中显示了两行,一个是之前选择的国家,一个是在国家之后选择并基于时间选择我们能够优化流程。现在在我们的国家下拉列表中,我们列出了前 5 个最近/经常出现的国家,因此这些用户不再需要滚动并选择一个国家;它更快。

【讨论】:

  • 我们只对每日加载的数据运行 bigquery 并生成每日报告。我们将把这些每日报告导出到存储中并转储到elasticsearch,这将是我们的输出api,所以保持我们的bigquery数据干净。我可以在应用层控制不允许重复的数据加载。另外为了在 BigQuery 层上添加防错检查,我可以在批量加载之前进行一次 DML 操作,在加载该日期的数据之前删除该日期的所有数据。这是一个好习惯吗?
  • 我们在谈论什么体积?如果您将所有内容都保留在 BQ 中并调整查询以读取最后一行,这不是更容易吗?
  • 目前,数量约为数百万。以后可能会变大。有一些关于大查询的连接查询和聚合(group by 的总和/平均值等)以获得我们的最终结果。对于输出 api,elasticsearch 会更高效。我们将副本保留在存储中,只是为了以防万一。
  • 调整查询以读取每一行的最新版本是有意义的,但是您需要一个时间戳列。它必须明确定义还是默认存在?鉴于 GBQ 是一个数据湖,我希望它默认存在。
  • 自 2020 年 3 月起,DML 操作在 bigquery 中不再有报价限制:cloud.google.com/blog/products/data-analytics/…
【解决方案2】:
【解决方案3】:

“批量删除和插入”是我用来避免重复记录的方法。而谷歌自己的“Youtube BigQuery Transfer Services”也在使用“批量删除和插入”。

“Youtube BigQuery Transfer Services”每天将每日报告推送到同一组报告表中。每条记录都有一个“日期”列。

当我们运行 Youtube Bigquery Transfer 回填时(要求 youtube bigquery transfer 再次推送特定日期的报告。)Youtube BigQury Transfer 服务将首先在报告表中删除该日期的完整数据集,然后插入完整的数据集再次回到报告表。

另一种方法是先删除结果表(如果它已经存在),然后重新创建结果表并再次将结果重新输入到表中。我经常使用这种方法。每天,我都将我的过程数据结果保存在日常数据集中的一些结果表中。如果我重新运行当天的流程,我的脚本将检查当天的结果表是否存在。如果当天存在表,则删除该表,然后重新创建一个新表,然后将处理结果重新输入到新创建的表中。

【讨论】:

  • “批量删除和插入”- 如果适用,我们应该使用分区。只需删除分区副本并添加新分区副本即可。
  • 您将如何处理UPDATE or DELETE statement over table *** would affect rows in the streaming buffer, which is not supported 错误?
  • 我现在没有使用流媒体。我将数据加载到 Google Cloud Storage Bucket,然后将数据从 GCP 存储桶加载到 BigQuery。这解决了很多流式传输到 BigQuery 的问题。另外,我会尽量少用更新和删除。
  • 啊,有趣的是,您使用什么流程/API 将 GCS 中的 (json) 数据获取到 BQ 中?或者你只是使用 UI 来做到这一点?我正在寻找一种自动化的方法。
  • 我曾经使用 php 客户端库将数据从存储加载到 BigQuery。当然,我还需要先使用 php 客户端库将数据加载到存储中。比必要的工作多一点。所以我使用流媒体来减少步骤。但是流媒体存在所有这些问题。现在我们使用气流(Google Cloud Composer),即使我们不能跳过将数据加载到存储然后将数据从存储加载到 bigquery 的步骤。但是气流具有您可以使用的所有这些运算符,airflow.apache.org/docs/stable/_api/airflow/contrib/operators/…
猜你喜欢
  • 1970-01-01
  • 2014-04-08
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 2016-08-24
  • 1970-01-01
  • 1970-01-01
  • 2013-08-10
相关资源
最近更新 更多