6月,BQ团队announced support for date-partitioned tables。但是指南缺少如何将旧的非分区表迁移到新样式中。
我正在寻找一种方法来将几个或者不是所有的表更新为新样式。
在DAY类型之外还划分了其他可用选项吗? BQ UI是否显示了这一点,因为我无法从BQ Web UI创建这样一个新的分区表。
答案 0 :(得分:14)
来自Pavan的回答:请注意,这种方法会向您收取查询源表的扫描成本。查询次数。
<小时/> 来自Pentium10评论:所以假设我有几年的数据,我需要为每天准备不同的查询并运行所有这些,并假设我有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
使用pivot_table(或任何名称首选)在Web UI中运行上述查询作为目标
正如我们所看到的 - 这里我们将获得包含10列的表 - 一天有一列,每列的模式是原始表的模式副本:
步骤2 - 逐个处理分区仅扫描相应列(无全表扫描) - 插入相应分区
#standardSQL
SELECT r.*
FROM pivot_table, UNNEST(day20170101) AS r
从Web UI运行上面的查询,目标表名为mytable $ 20160101
您可以在第二天运行相同的
#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)]
答案 1 :(得分:7)
在BigQuery中推出新功能之前,还有另一种(便宜得多的)方法可以使用Cloud Dataflow对表进行分区。我们使用这种方法而不是运行数百个SELECT *
语句,这将花费我们数千美元。
partition
命令BigQuery.IO.Read
接收器来读取表格BigQuery.IO.Write
接收器,使用分区装饰器写入相应的分区语法 - "$YYYYMMDD"
Here's an example on Github让你开始。
您仍然需要为数据流管道付费,但它只是在BigQuery中使用多个SELECT *
的一小部分。
答案 2 :(得分:6)
截至今天,您现在可以通过查询并指定分区列,从非分区表创建分区表。您将在原始(未分区)表上支付一次全表扫描费用。 注意:目前处于测试阶段。
要从查询结果创建分区表,请将结果写入新目标表。您可以通过查询分区表或非分区表来创建分区表。您无法使用查询结果将现有标准表更改为分区表。
答案 3 :(得分:4)
如果您今天有日期分片表,则可以使用此方法:
如果要将单个非分区表转换为分区表,则可以尝试运行SELECT *查询并允许大结果并使用表的分区作为目标(类似于如何你重新分区的数据):
https://cloud.google.com/bigquery/docs/creating-partitioned-tables#restating_data_in_a_partition
请注意,此方法会向您收取查询源表的扫描成本,与您查询的次数一样多。
我们正在努力使这种情况在未来几个月内显着改善。
答案 4 :(得分:2)
对我有用的是以下直接在大查询中应用的查询集(大查询创建新查询)。
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步