使用bigquery将表拆分为基于日期的多个表,并使用单个查询进行分区

时间:2017-02-03 18:51:56

标签: google-bigquery

我想做的最初“为什么”是:

恢复一个保持原始分区的表,而不是全部进入今天的分区。

我认为我可以做bq load到临时表。然后运行查询以在bq partition所需的命名约定中将该表拆分为每天YYYYMMDD一个表,即sharded_YYYYMMDD。然后运行bq partition

此页面https://cloud.google.com/bigquery/docs/creating-partitioned-tables提供了示例,但它需要每天运行查询。那可能是几百个:

bq query --use_legacy_sql=false --allow_large_results --replace \ --noflatten_results --destination_table 'mydataset.temps$20160101' \ 'SELECT stn,temp from `bigquery-public-data.noaa_gsod.gsod2016` WHERE mo="01" AND da="01" limit 100'

那么如何制作一个会在一天中迭代并且每天制作一个表的单个查询呢?

我在这里找到了一个类似的问题Split a table into multiple tables in BigQuery SQL但是没有回答用单个查询来做这件事。

2 个答案:

答案 0 :(得分:3)

这里的主要问题是每天都要进行全面扫描。剩下的不是问题,可以在任何client of your choice

中轻松编写脚本

因此,以下是 - 如何避免每天全表扫描?

尝试以下步骤查看方法
它足够通用,可以扩展/适用于您的实际案例 - 同时我在您的问题中使用与您相同的示例,我将锻炼限制在10天

步骤1 - 创建数据透视表
在这一步中,我们a)将每一行的内容压缩成记录/数组,并b)将它们全部放入相应的“每日”列中

  
insertID

使用pivot_table在Web UI中运行上述查询(您可以在此处选择您想要的任何名称)作为目的地

正如您所看到的 - 这里我们将获得包含10列的表 - 一天有一列,每列的模式是原始表的模式副本:

enter image description here

步骤2 - 逐个创建分片表仅扫描相应列(无全表扫描)

#standardSQL
SELECT
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20160101' THEN r END) AS day20160101,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20160102' THEN r END) AS day20160102,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20160103' THEN r END) AS day20160103,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20160104' THEN r END) AS day20160104,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20160105' THEN r END) AS day20160105,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20160106' THEN r END) AS day20160106,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20160107' THEN r END) AS day20160107,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20160108' THEN r END) AS day20160108,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20160109' THEN r END) AS day20160109,
  ARRAY_CONCAT_AGG(CASE WHEN d = 'day20160110' THEN r END) AS day20160110
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.gsod2016` AS t 
    GROUP BY stn, d
  ) 
)
GROUP BY line

使用名为mytable_20160101

的目标表从Web UI运行上述查询

您可以在第二天运行相同的

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

现在你应该有名为mytable_20160102的目的地表等等 您应该能够使用您选择的任何客户端自动执行/编写此步骤 注意:那些最终的每日表将与原始表具有完全相同的模式!

如何使用上述方法有很多变化 - 这取决于你的创造力

注意:BigQuery允许表中最多10000列,因此一年中相应日期的365列绝对不是问题:o)

答案 1 :(得分:0)

在这里回答自己。我见过的另一种方法是编写一个脚本:

  1. 解析tablebackup.json文件,输出分配在提供的参数上的多个文件tablebackuppartitionYYYYMMDD.json

  2. 创建一个批处理脚本,将bq load所有文件放入相应的表分区。

  3. 脚本需要逐行或多块处理才能处理大量备份。并且需要一些时间。使用这种方法的优点是它是通用的,可由未经训练的BQ系统管理员使用。