【问题标题】:BigQuery updates failing, but only when batched using Python APIBigQuery 更新失败,但仅在使用 Python API 进行批处理时
【发布时间】:2019-03-14 15:41:11
【问题描述】:

我正在尝试使用批量更新语句更新表。 DML 查询在 BigQuery Web UI 中成功执行,但在批处理时,第一个查询成功,而其他查询失败。这是为什么呢?

示例查询:

query = '''
update `project.dataset.Table`
set my_fk = 1234
where other_fk = 222 and
  received >= PARSE_TIMESTAMP("%Y-%m-%d %H:%M:%S", "2018-01-22 05:28:12") and 
  received <= PARSE_TIMESTAMP("%Y-%m-%d %H:%M:%S", "2018-01-26 02:31:51")
'''

示例代码:

job_config = bigquery.QueryJobConfig()
job_config.priority = bigquery.QueryPriority.BATCH

queries = [] # list of DML Strings
jobs = []
for query in queries:
    job = client.query(query, location='US', job_config=job_config)
    jobs.append(job)

工作输出:

for job in jobs[1:]:
    print(job.state)
    # Done

    print(job.error_result)
    # {'message': 'Cannot set destination table in jobs with DML statements',
    # 'reason': 'invalidQuery'}

    print(job.use_legacy_sql)
    # False

    print(job.job_type)
    # Query

【问题讨论】:

  • 您是否对所有批处理作业重复使用相同的job_config
  • 我是。我不应该吗?
  • BigQuery API 将填充一些字段,因此,在第一个作业的响应之后,目标表将是非空的。然后,第二个将失败。您可以在第一次通话前后与print(job_config.destination) 进行验证

标签: google-bigquery


【解决方案1】:

我怀疑问题在于job_config 在插入第一个作业后,BigQuery API 填充了一些字段(特别是destination)。然后,第二个作业将失败,因为它将是作业配置中带有目标表的 DML 语句。您可以通过以下方式验证:

for query in queries:
    print(job_config.destination)
    job = client.query(query, location='US', job_config=job_config)
    print(job_config.destination)
    jobs.append(job)

要解决这个问题,您可以避免对所有作业重复使用相同的 job_config

for query in queries:
    job_config = bigquery.QueryJobConfig()
    job_config.priority = bigquery.QueryPriority.BATCH
    job = client.query(query, location='US', job_config=job_config)
    jobs.append(job)

【讨论】:

    【解决方案2】:

    您的代码似乎在一次更新时运行良好。这是我尝试使用 python 3.6.5 和 v1.9.0 的客户端 API

    from google.cloud import bigquery
    client = bigquery.Client()
    
    query = '''
    UPDATE `project.dataset.table` SET msg = null WHERE x is null
    '''
    
    job_config = bigquery.QueryJobConfig()
    job_config.priority = bigquery.QueryPriority.BATCH
    job = client.query(query, location='US', job_config=job_config)
    
    print(job.state)
    # PENDING
    
    print(job.error_result)
    #  None
    
    print(job.use_legacy_sql)
    # False
    
    print(job.job_type)
    # Query
    

    如果这不能帮助您解决问题,请检查您的配置并提供带有错误日志的完整代码

    顺便说一句,我也从命令行验证了这一点

    sh-3.2# ./bq query --nouse_legacy_sql --batch=true 'UPDATE `project.dataset.table` SET msg = null WHERE x is null'
    Waiting on bqjob_r5ee4f5dd56dc212f_000001697d3f9a56_1 ... (133s) Current status: RUNNING
    Waiting on bqjob_r5ee4f5dd56dc212f_000001697d3f9a56_1 ... (139s) Current status: DONE
    sh-3.2#
    sh-3.2# python --version
    

    【讨论】:

    • 感谢您的检查。我已经编辑了我的代码以表明我正在迭代许多类似的查询。 @guillem-xercavins 对我正在测试的 job_config 提出了一个很好的观点
    猜你喜欢
    • 2016-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-06
    • 2013-10-13
    • 1970-01-01
    • 2018-06-22
    • 2016-06-23
    相关资源
    最近更新 更多