我要导出的BigQuery中有一个按日期分区的表。我想将其导出,以使每天的数据最终保存在另一个文件中。例如,到具有gs://my-bucket/YYYY/MM/DD/
之类的嵌套文件夹结构的GS存储桶。这可能吗?
请不要告诉我我需要为每天的数据运行一个单独的导出作业:我知道这是可能的,但是在导出许多年的数据时,这很痛苦,因为您需要运行数千个导出作业。
在进口方面,可以使用镶木地板格式。
如果直接使用BigQuery无法做到这一点,那么是否有像dataproc或dataflow这样的GCS工具可以简化此工作(链接到实际执行此导出的脚本的要点)。
答案 0 :(得分:1)
使用bq extract的bash脚本可以工作吗?
#!/bin/bash
# Stop on first error
set -e;
# Used for Bigquery partitioning (to distinguish from bash variable reference)
DOLLAR="\$"
# -I ISO DATE
# -d FROM STRING
start=$(date -I -d 2019-06-01) || exit -1
end=$(date -I -d 2019-06-15) || exit -1
d=${start}
# string(d) <= string(end)
while [[ ! "$d" > "$end" ]]; do
YYYYMMDD=$(date -d ${d} +"%Y%m%d")
YYYY=$(date -d ${d} +"%Y")
MM=$(date -d ${d} +"%m")
DD=$(date -d ${d} +"%d")
# print current date
echo ${d}
cmd="bq extract --destination_format=AVRO \
'project:dataset.table${DOLLAR}${YYYYMMDD}' \
'gs://my-bucket/${YYYY}/${MM}/${DD}/part*.avro'
"
# execute
eval ${cmd}
# d++
d=$(date -I -d "$d + 1 day")
done
也许您应该在https://issuetracker.google.com/savedsearches/559654上请求一项新功能。
不是bash忍者,所以请确保有一种比较酷的日期比较方法。
答案 1 :(得分:0)
在@Ben P的要求下,这是我以前用来并行运行许多导出作业的解决方案(python脚本)。这是相当粗糙的代码,应该通过在每个导出作业运行后检查其状态是否成功来进行改进。
我不会接受这个答案,因为问题正在寻找一种执行本任务的大查询本机方式。
请注意,此脚本用于导出版本化的数据集,因此围绕许多用户可能不需要的逻辑。假定输入表和输出文件夹名称都使用该版本。这应该很容易删除。
import argparse
import datetime as dt
from google.cloud import bigquery
from multiprocessing import Pool
import random
import time
GCS_EXPORT_BUCKET = "YOUR_BUCKET_HERE"
VERSION = "dataset_v1"
def export_date(export_dt, bucket=GCS_EXPORT_BUCKET, version=VERSION):
table_id = '{}${:%Y%m%d}'.format(version, export_dt)
gcs_filename = '{}/{:%Y/%m/%d}/{}-*.jsonlines.gz'.format(version, export_dt, table_id)
gcs_path = 'gs://{}/{}'.format(bucket, gcs_filename)
job_id = export_data_to_gcs(table_id, gcs_path, 'currents')
return (export_dt, job_id)
def export_data_to_gcs(table_id, destination_gcs_path, dataset):
bigquery_client = bigquery.Client()
dataset_ref = bigquery_client.dataset(dataset)
table_ref = dataset_ref.table(table_id)
job_config = bigquery.job.ExtractJobConfig()
job_config.destination_format = 'NEWLINE_DELIMITED_JSON'
job_config.compression = 'GZIP'
job_id = 'export-{}-{:%Y%m%d%H%M%S}'.format(table_id.replace('$', '--'),
dt.datetime.utcnow())
# Add a bit of jitter
time.sleep(5 * random.random())
job = bigquery_client.extract_table(table_ref,
destination_gcs_path,
job_config=job_config,
job_id=job_id)
print(f'Now running job_id {job_id}')
time.sleep(50)
job.reload()
while job.running():
time.sleep(10)
job.reload()
return job_id
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-s', "--startdate",
help="The Start Date - format YYYY-MM-DD (Inclusive)",
required=True,
type=dt.date.fromisoformat)
parser.add_argument('-e', "--enddate",
help="The End Date format YYYY-MM-DD (Exclusive)",
required=True,
type=dt.date.fromisoformat)
args = parser.parse_args()
start_date = args.startdate
end_date = args.enddate
dates = []
while start_date < end_date:
dates.append(start_date)
start_date += dt.timedelta(days=1)
with Pool(processes=30) as pool:
jobs = pool.map(export_date, dates, chunksize=1)
要运行此代码,请将其放入名为bq_exporter.py
的文件中,然后运行python bq_exporter.py -s 2019-01-01 -e 2019-02-01
。该操作将在2019年1月导出,并打印每个导出作业的ID。您可以通过bq show -j JOB_ID
使用BigQuery CLI检查作业的状态。