如何在BigQuery数据集中合并一千张表?

时间:2019-10-25 16:11:53

标签: sql google-cloud-platform google-bigquery google-cloud-functions

我在BigQuery中有一个约有1000个表的数据集,每个变量一个。每个表包含两列:observation_number,variable_name。请注意,variable_name列采用实际的变量名。每个表至少包含20000行。在观察号上合并这些表的最佳方法是什么?

我已经开发了将在Cloud Function上运行的Python代码,并且它生成SQL查询以合并表。通过连接到数据集并遍历表以获取所有table_id,可以做到这一点。但是,查询最终太大,性能也不是很好。

这里是生成查询的Python代码示例(请注意,它仍在本地运行,尚未在Cloud Function中运行)。

from google.cloud import bigquery

# Construct a BigQuery client object.
client = bigquery.Client()

# TODO(developer): Set project_id and dataset_id.
project_id = 'project-id-gcp'
dataset_name = 'sample_dataset'
dataset_id = project_id+'.'+dataset_name

dataset = client.get_dataset(dataset_id)

# View tables in dataset
tables = list(client.list_tables(dataset))  # API request(s)
table_names = []

if tables:
    for table in tables:
        table_names.append(table.table_id)
else:
    print("\tThis dataset does not contain any tables.")

query_start = "select "+table_names[0]+".observation"+","+table_names[0]+"."+table_names[0]
query_select = ""
query_from_select = "(select observation,"+table_names[0]+" from `"+dataset_name+"."+table_names[0]+"`) "+table_names[0]
for table_name in table_names:
    if table_name != table_names[0]:
        query_select = query_select + "," + table_name+"."+table_name
        query_from_select = query_from_select + " FULL OUTER JOIN (select observation," + table_name + " from " + "`"+dataset_name+"."+table_name+"`) "+table_name+" on "+table_names[0]+".observation="+table_name+".observation"
query_from_select = " from ("+query_from_select + ")"
query_where = " where " + table_names[0] + ".observation IS NOT NULL"
query_order_by = " order by observation"

query_full = query_start+query_select+query_from_select+query_where+query_order_by

with open("query.sql","w") as f:
    f.write(query_full)

这是针对两个表生成的查询的示例:

select 
  VARIABLE1.observation, 
  VARIABLE1.VARIABLE1, 
  VARIABLE2.VARIABLE2 
from 
  (
    (
      select 
        observation, 
        VARIABLE1 
      from 
        `sample_dataset.VARIABLE1`
    ) VARIABLE1 FULL 
    OUTER JOIN (
      select 
        observation, 
        VARIABLE2 
      from 
        `sample_dataset.VARIABLE2`
    ) VARIABLE2 on VARIABLE1.observation = VARIABLE2.observation
  ) 
where 
  VARIABLE1.observation IS NOT NULL 
order by 
  observation

随着表数量的增加,该查询越来越大。关于如何改善此操作性能的任何建议?还有其他方法可以解决此问题吗?

1 个答案:

答案 0 :(得分:2)

我不知道这个问题是否有很好的技术答案。似乎您正在尝试在单个查询中执行大量的连接,而很多连接并不能实现BQ的优势。

虽然我在下面概述了一个潜在的解决方案,但您是否考虑过/为什么真的需要一个包含1000多个潜在列的表?并不是说您没有,但是可能有其他方法可以解决您的问题而无需创建如此复杂的表。

一个可能的解决方案是将您的联接/表分成更易于管理的块。 例如,如果您有1000个表,请对表的较小子集(2/5/10 / etc)运行脚本,然后将这些结果写入中间表。然后加入您的中间表。这可能需要几层中间表,具体取决于子表的大小。基本上,您想最小化(或合理化)每个查询中的联接数。完成操作后,请删除中间表,以减少不必要的存储成本。