【问题标题】:Migrating from non-partitioned to Partitioned tables从非分区表迁移到分区表
【发布时间】:2016-12-23 22:46:21
【问题描述】:

6 月 BQ 团队announced support for date-partitioned tables。但是该指南缺少如何将旧的非分区表迁移到新样式中。

我正在寻找一种方法来更新几个或者如果不是所有的表格到新的样式。

除了 DAY 类型的分区之外还有哪些其他选项可用? BQ UI 是否显示了这一点,因为我无法从 BQ Web UI 创建这样一个新的分区表。

【问题讨论】:

标签: google-bigquery


【解决方案1】:

对我有用的是直接在大查询中应用的以下一组查询(大查询创建新查询)。

CREATE TABLE (new?)dataset.new_table PARTITION BY DATE(date_column) AS SELECT * FROM dataset.table_to_copy;

然后作为下一步我删除表格:

DROP TABLE dataset.table_to_copy;

我从https://fivetran.com/docs/warehouses/bigquery/partition-table 得到了这个解决方案 仅使用第 2 步

【讨论】:

  • 谢天谢地,我在尝试接受的答案之前看到了您的答案。
【解决方案2】:

来自 Pavan 的回答:请注意,这种方法会根据您查询的次数向您收取查询的源表的扫描成本。


来自 Pentium10 cmets:所以假设我有几年的数据,我需要为每天准备不同的查询并运行所有数据,假设我有 1000 天的历史记录,我需要支付 1000 倍的全部查询价格来自源表?

正如我们所见 - 这里的主要问题是每天都进行全面扫描。其余的问题不大,可以在任何client of the choice 中轻松编写脚本

那么,下面是 - 如何在避免每天进行全表扫描的同时对表进行分区?

下面一步一步显示方法

它足够通用,可以扩展/适用于任何实际用例 - 同时我正在使用 bigquery-public-data.noaa_gsod.gsod2017,并且我将“练习”限制为仅 10 天以保持其可读性

第 1 步 - 创建数据透视表
在这一步中,我们
a) 将每一行的内容压缩到记录/数组中

b)将它们全部放入各自的“每日”列

#standardSQL
SELECT
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20170101' THEN r END) AS day20170101,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20170102' THEN r END) AS day20170102,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20170103' THEN r END) AS day20170103,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20170104' THEN r END) AS day20170104,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20170105' THEN r END) AS day20170105,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20170106' THEN r END) AS day20170106,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20170107' THEN r END) AS day20170107,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20170108' THEN r END) AS day20170108,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20170109' THEN r END) AS day20170109,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20170110' THEN r END) AS day20170110
FROM (
  SELECT d, r, ROW_NUMBER() OVER(PARTITION BY d) AS line
  FROM (
    SELECT 
      stn, CONCAT('day', year, mo, da) AS d, ARRAY_AGG(t) AS r
    FROM `bigquery-public-data.noaa_gsod.gsod2017` AS t 
    GROUP BY stn, d
  ) 
)
GROUP BY line  

在 Web UI 中以 pivot_table(或任何首选名称)作为目标运行上述查询

如我们所见 - 在这里我们将获得 10 列的表 - 一天一列,每列的架构是原始表架构的副本:

第 2 步 – 一个接一个地处理分区,只扫描相应的列(没有全表扫描) – 插入到相应的分区中

#standardSQL
SELECT r.*
FROM pivot_table, UNNEST(day20170101) AS r

使用名为 mytable$20160101 的目标表从 Web UI 运行上述查询

你可以在第二天继续运行

#standardSQL
SELECT r.*
FROM pivot_table, UNNEST(day20170102) AS r

现在你的目标表应该是 mytable$20160102 等等

您应该能够使用您选择的任何客户端自动执行此步骤/编写脚本

您可以如何使用上述方法有很多变体 - 这取决于您的创造力

注意:BigQuery 最多允许表中包含 10000 列,因此一年中的相应天数为 365 列绝对不是问题 :o) 除非对新分区的回溯有限制——我听说(但还没有机会检查)现在回溯不超过 90 天

更新

请注意: 上面的版本有一点额外的逻辑,将所有聚合单元格打包成尽可能少的最终行数。

ROW_NUMBER() OVER(PARTITION BY d) AS line
然后
GROUP BY line
还有
ARRAY_CONCAT_AGG(…)
这样做

当原始表中的行大小没有那么大时,这很有效,因此最终组合的行大小仍将在 BigQuery 的行大小限制内(我认为目前为 10 MB)

如果您的源表的行大小已经接近该限制 - 请使用以下调整后的版本

在这个版本中 - 分组被删除,使得每一行只有一列的值

#standardSQL
SELECT
    CASE WHEN d = 'day20170101' THEN r END AS day20170101,
    CASE WHEN d = 'day20170102' THEN r END AS day20170102,
    CASE WHEN d = 'day20170103' THEN r END AS day20170103,
    CASE WHEN d = 'day20170104' THEN r END AS day20170104,
    CASE WHEN d = 'day20170105' THEN r END AS day20170105,
    CASE WHEN d = 'day20170106' THEN r END AS day20170106,
    CASE WHEN d = 'day20170107' THEN r END AS day20170107,
    CASE WHEN d = 'day20170108' THEN r END AS day20170108,
    CASE WHEN d = 'day20170109' THEN r END AS day20170109,
    CASE WHEN d = 'day20170110' THEN r END AS day20170110
FROM (
    SELECT 
        stn, CONCAT('day', year, mo, da) AS d, ARRAY_AGG(t) AS r
    FROM `bigquery-public-data.noaa_gsod.gsod2017` AS t 
    GROUP BY stn, d
)
WHERE d BETWEEN 'day20170101' AND 'day20170110'

正如您现在所看到的 - 数据透视表 (sparce_pivot_table) 足够稀疏(相同的 21.5 MB,但现在 114,089 行与 pivot_table 中的 11,584 行相比),因此它的平均行大小为 190B,而初始版本为 1.9KB。这显然比示例中的列数少 10 倍。
所以在使用这种方法之前,需要做一些数学运算来预测/估计可以做什么以及如何做!

仍然:数据透视表中的每个单元格都是原始表中整行的 JSON 表示。它不仅包含原始表中行的值,而且还包含模式

因此它非常冗长 - 因此单元格的大小可能比原始大小大几倍[这限制了这种方法的使用......除非你更有创意:o)......这仍然很多这里申请的领域:o)]

【讨论】:

  • 哇。现在要测试这个。那个 Mikhail 是什么工具/UI?
  • @GrahamPolley - 已经很长时间没有使用 BigQuery Web UI,顺便说一句,这并不能帮助我很好地维护 BQ Mate,所以我真的依赖于用户的反馈 - 仍在努力保持它更新并在需要时进行修复并有一些空闲时间。
  • @GrahamPolley - 截至 - what tool/UI is this? - 这是我必须根据业务用户的需求(当然是与我的团队)创建的少数工具之一 - 这弥补了谷歌网络中缺乏的许多功能用户界面。当它无法按需要执行时,我们就到了这一点——甚至在我们的数量和规模上大部分都崩溃了。我们已经使用/使用这些工具几年了——BQ 团队正在慢慢添加一些功能/改进,但距离我们需要的东西(并且在我们的内部工具中)还有很长的路要走
  • 这可能是我在 Stackoverflow Mikhail 上看到的最巧妙的解决方案(无论如何对于 BigQuery)。非常尊重! (赞成)
  • BigQuery 对行大小没有 ~10 或 ~20MB 的限制,这在除小型数据集之外的任何东西上都无法使用此方法(无论如何,表扫描都很便宜)?
【解决方案3】:

从今天开始,您现在可以通过查询非分区表并指定分区列来从非分区表创建分区表。您将支付对原始(非分区)表进行一次全表扫描的费用。 注意:目前处于测试阶段。

https://cloud.google.com/bigquery/docs/creating-column-partitions#creating_a_partitioned_table_from_a_query_result

要根据查询结果创建分区表,请将结果写入新的目标表。您可以通过查询分区表或非分区表来创建分区表。您不能使用查询结果将现有标准表更改为分区表。

【讨论】:

  • 我们也可以使用 Java 客户端来实现吗?我正在使用客户端 version1.34.0,似乎没有选择分区选项的选项。这仅在 REST API 中支持吗?
  • 当我说 REST API 时,我指的是旧 API。谢谢
【解决方案4】:

在 BigQuery 中推出新功能之前,还有另一种(更便宜)的方法来使用 Cloud Dataflow 对表进行分区。我们使用这种方法而不是运行数百个 SELECT * 语句,这将花费我们数千美元。

  1. 使用普通的partition 命令在 BigQuery 中创建分区表
  2. 创建 Dataflow 管道并使用 BigQuery.IO.Read 接收器读取表
  3. 使用Partition transform 对每一行进行分区
  4. 一次最多使用 200 个分片/接收器(超过此数量,您会达到 API 限制),为每天/分片创建一个 BigQuery.IO.Write 接收器,它将使用分区装饰器语法写入相应的分区 - "$YYYYMMDD"
  5. 重复 N 次,直到处理完所有数据。

Here's an example on Github 让您开始。

您仍然需要为 Dataflow 管道付费,但这只是在 BigQuery 中使用多个 SELECT * 的成本的一小部分。

【讨论】:

    【解决方案5】:

    如果你今天有日期分片表,你可以使用这种方法:

    https://cloud.google.com/bigquery/docs/creating-partitioned-tables#converting_dated_tables_into_a_partitioned_table

    如果您有一个非分区表要转换为分区表,您可以尝试运行 SELECT * 查询并允许大结果并使用表的分区作为目标的方法(类似于您重述的方式分区的数据):

    https://cloud.google.com/bigquery/docs/creating-partitioned-tables#restating_data_in_a_partition

    请注意,这种方法会根据您查询的次数向您收取查询的源表扫描成本。

    我们正在努力在未来几个月内使这种情况显着改善。

    【讨论】:

    • 如何使用第二种方法确保架构是 DAY 类型?除了 DAY,我们还有哪些类型?
    • 我有一个时间戳字段,我想用它来分区。我如何告诉系统它应该使用该字段?
    • 所以假设我有几年的数据,我需要为每天准备不同的查询并运行所有数据,假设我有 1000 天的历史,我需要支付 1000 倍的完整查询源表中的价格?如果这是真的,那就“难以置信”。
    • 我们正在积极努力使单个查询能够做到这一点,但目前可以使用年、月、日拆分策略来降低成本。首先划分为多个年表,然后将每个划分为月表,然后将每个划分为日表。我们知道这对用户来说既昂贵又麻烦,因此我们希望尽快有一个更简单、更便宜的解决方案。谢谢。
    • @PavanEdara 对此有何更新?否则对我的团队来说将是一个巨大、丑陋、昂贵的转换:(
    猜你喜欢
    • 2018-09-20
    • 1970-01-01
    • 2015-11-07
    • 2018-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多