如何通过BigQuery Client获取子DML任务的num_dml_affected_rows值
多语句脚本下获取DML影响行数的实现方案
问题根因
多语句脚本提交后会被BigQuery拆分为1个父任务和多个独立子任务,父任务本身不直接执行单条语句,因此自身的num_dml_affected_rows字段固定返回None,不会自动聚合所有子任务的DML统计值。
尝试直接通过*query_job.children_job[-1]*获取值失效的核心原因是:Python客户端不会自动加载并缓存当前主任务关联的所有子任务列表,该路径下没有有效可读取的属性数据。
具体实现步骤
- 等待主任务执行完成后,先获取主任务的基础标识(项目ID、资源位置、任务ID)
- 调用客户端的任务列表查询能力,通过父任务ID过滤拉取所有关联子任务
- 遍历子任务列表,提取每个DML子任务的
num_dml_affected_rows值
对应的示例代码:
from google.cloud.bigquery.job import JobReference # 等待主任务执行完成 query_job.result() # 构造子任务查询条件 job_ref = JobReference( project=query_job.project, location=query_job.location, job_id=query_job.job_id ) # 拉取所有关联子任务,按创建时间升序对齐SQL执行顺序 child_jobs = sorted( bigquery.Client().list_jobs( parent_job=job_ref, min_creation=query_job.created, all_users=False ), key=lambda job: job.created ) # 提取所有DML语句的影响行数 dml_affected_rows_list = [ job.num_dml_affected_rows for job in child_jobs if job.num_dml_affected_rows is not None ]
常见注意事项
- 任务列表查询默认返回的子任务是按创建时间倒序排列,必须手动按创建时间升序排序,才能和脚本中SQL的执行顺序一一对应,避免取错任务的统计值
- 非DML类型的子任务(比如SELECT查询、DDL语句)的
num_dml_affected_rows本身为空值,需要做过滤再取值 - 该方案不需要额外的特殊权限,和执行普通查询的权限要求一致
方案对比优势
相比之前用执行前后表行数差值计算的临时方案,该方案:
- 不需要额外执行两次全表count查询,节省Slot资源和执行耗时
- 统计结果不受脚本执行过程中其他并发写入任务的干扰,数值精准
- 可以一次性拿到脚本内所有DML语句的各自影响行数,不需要单独定位最后一条DML的结果
内容的提问来源于stack exchange,提问作者Jiho Choi
相关产品推荐
相关产品推荐

