BigQuery导出至GCS无数据却生成0字节文件如何解决?
解决BigQuery EXPORT DATA无数据时生成空文件的问题
问题原因
BigQuery的EXPORT DATA操作本身的机制是:即使查询结果为空,它也会按照指定的URI模式创建空文件。这是因为BigQuery采用分布式执行框架,分片任务会预先创建文件占位,不管最终有没有数据写入。
解决方案:提前判断数据量再执行导出
要避免无数据时生成空文件,核心思路是先检查查询结果是否有数据,只有当数据量大于0时才执行导出操作。以下是两种可行的实现方式:
1. 使用BigQuery脚本(纯SQL实现)
通过BigQuery的脚本功能,先统计符合条件的行数,再根据行数决定是否执行导出:
DECLARE row_count INT64; -- 先统计目标数据的行数 SET row_count = ( SELECT COUNT(DISTINCT *) FROM `<<PROJECT>>.<<DATASET>>.VWE_<<TABLE>>` WHERE CAST(LASTLOADDATE AS DATETIME) > DATETIME_SUB(CURRENT_DATE(), INTERVAL 2 DAY) AND LASTLOADDATE IS NOT NULL ); -- 只有行数大于0时才执行导出 IF row_count > 0 THEN EXPORT DATA OPTIONS ( uri = 'gs://<<BUCKET>>/<<TABLE>>*.csv', format = 'CSV', overwrite = true, header = false, field_delimiter = '|' ) AS SELECT DISTINCT * FROM `<<PROJECT>>.<<DATASET>>.VWE_<<TABLE>>` WHERE CAST(LASTLOADDATE AS DATETIME) > DATETIME_SUB(CURRENT_DATE(), INTERVAL 2 DAY) AND LASTLOADDATE IS NOT NULL; END IF;
2. 使用命令行脚本(bash + bq命令)
如果是通过命令行调度导出任务,可以先执行计数查询,再判断是否触发导出:
# 统计目标数据行数 ROW_COUNT=$(bq query --quiet --format=csv "SELECT COUNT(DISTINCT *) FROM \`<<PROJECT>>.<<DATASET>>.VWE_<<TABLE>>\` WHERE CAST(LASTLOADDATE AS DATETIME) > DATETIME_SUB(CURRENT_DATE(), INTERVAL 2 DAY) AND LASTLOADDATE IS NOT NULL" | tail -n 1) # 行数大于0时执行导出 if [ "$ROW_COUNT" -gt 0 ]; then bq extract \ --destination_format CSV \ --field_delimiter "|" \ --no_header \ --replace \ `<<PROJECT>>.<<DATASET>>.VWE_<<TABLE>>` \ gs://<<BUCKET>>/<<TABLE>>*.csv fi
补充:事后清理空文件(备选方案)
如果无法提前判断,也可以在导出完成后删除GCS上的0字节文件:
gsutil ls -l gs://<<BUCKET>>/<<TABLE>>*.csv | awk '$1 == 0 {print $3}' | xargs gsutil rm
这种方式适合已经生成空文件的场景,但不如提前判断高效。
内容的提问来源于stack exchange,提问作者arcee123
相关产品推荐
相关产品推荐

