GCP BigQuery 命令
BigQuery 命令实战:bq 工具、数据集与表管理、查询作业、数据加载导出与流式插入。
学习目标
本文是「云计算」模块的第 52 篇,难度定位为入门。重点内容:BigQuery 命令实战:bq 工具、数据集与表管理、查询作业、数据加载导出与流式插入。
主要章节:
- bq 工具基础
- 数据集管理
- 表操作
- 数据查询
- 数据加载
- 数据导出
- ……共 14 个章节
bq 工具基础
基本写法:查看帮助
bq --help
# 查看 bq 命令行工具帮助
bq --help
基本写法:查看版本
bq version
# 查看 bq 工具版本
bq version
基本写法:设置默认项目
gcloud config set project <项目ID>
# 设置 bq 操作的默认项目
gcloud config set project my-project-123
基本写法:指定项目运行
bq --project_id <项目ID> query <查询>
# 在指定项目下运行查询
bq --project_id my-project-123 query 'SELECT 1'
基本写法:设置查询位置
bq --location <位置> query <查询>
# 指定查询在 EU 区域执行
bq --location EU query 'SELECT 1'
数据集管理
基本写法:创建数据集
bq mk --dataset --location <位置> <项目>:<数据集>
# 创建 US 多区域数据集
bq mk --dataset --location US my-project-123:my_dataset
基本写法:列出数据集
bq ls [--project_id <项目ID>]
# 列出当前项目所有数据集
bq ls
基本写法:查看数据集信息
bq show <项目>:<数据集>
# 查看数据集详细信息
bq show my-project-123:my_dataset
基本写法:删除数据集
bq rm -r -d <数据集>
# 删除数据集及其所有表
bq rm -r -d my_dataset
基本写法:更新数据集
bq update --description <描述> <数据集>
# 更新数据集描述
bq update --description "用户分析数据集" my_dataset
表操作
基本写法:创建表
bq mk --table <项目>:<数据集>.<表> <字段:类型>
# 创建带 schema 的表
bq mk --table my_dataset.users \
user_id:STRING,name:STRING,age:INTEGER,created_at:TIMESTAMP
基本写法:列出表
bq ls <项目>:<数据集>
# 列出数据集中所有表
bq ls my_dataset
基本写法:查看表结构
bq show --schema <项目>:<数据集>.<表>
# 查看表 schema
bq show --schema --format=prettyjson my_dataset.users
基本写法:查看表详情
bq show <项目>:<数据集>.<表>
# 查看表详细信息
bq show my_dataset.users
基本写法:删除表
bq rm -t <项目>:<数据集>.<表>
# 删除指定表
bq rm -t my_dataset.users
基本写法:复制表
bq cp <源表> <目标表>
# 复制表到另一数据集
bq cp my_dataset.users my_dataset.users_backup
数据查询
基本写法:运行查询
bq query <SQL>
# 运行标准 SQL 查询
bq query 'SELECT * FROM my_dataset.users LIMIT 10'
基本写法:格式化输出
bq query --format <格式> <SQL>
# 以 JSON 格式输出
bq query --format=prettyjson 'SELECT * FROM my_dataset.users LIMIT 10'
基本写法:保存查询结果到表
bq query --destination_table <表> --use_legacy_sql=false <SQL>
# 查询结果保存到新表
bq query \
--destination_table my_dataset.results \
--use_legacy_sql=false \
'SELECT * FROM my_dataset.users WHERE age > 18'
基本写法:追加结果到表
bq query --destination_table <表> --append_table <SQL>
# 将结果追加到已有表
bq query \
--destination_table my_dataset.results \
--append_table \
'SELECT * FROM my_dataset.users WHERE age > 30'
基本写法:运行参数化查询
bq query --parameter=<参数> <SQL>
# 使用命名参数查询
bq query \
--parameter='min_age:INT64:21' \
'SELECT * FROM my_dataset.users WHERE age >= @min_age'
数据加载
基本写法:从本地 CSV 加载
bq load --source_format=CSV <数据集>.<表> <文件> <schema>
# 加载本地 CSV 文件到表
bq load --source_format=CSV \
my_dataset.users \
users.csv \
user_id:STRING,name:STRING,age:INTEGER
基本写法:从 GCS 加载
bq load --source_format=<格式> <表> <gs://路径>
# 从 Cloud Storage 加载 JSON 数据
bq load --source_format=NEWLINE_DELIMITED_JSON \
my_dataset.events \
gs://my-bucket/events/*.json \
event_id:STRING,event_type:STRING,timestamp:TIMESTAMP
基本写法:自动检测 schema
bq load --autodetect <表> <源>
# 自动检测 CSV 文件 schema
bq load --autodetect \
my_dataset.users \
gs://my-bucket/users.csv
基本写法:指定跳过行数
bq load --skip_leading_rows=<行数> <表> <源> <schema>
# 跳过 CSV 首行表头
bq load --skip_leading_rows=1 \
my_dataset.users \
gs://my-bucket/users.csv \
user_id:STRING,name:STRING,age:INTEGER
基本写法:从 Datastore 备份加载
bq load --source_format=DATASTORE_BACKUP <表> <gs://路径>
# 从 Datastore 备份导出加载
bq load --source_format=DATASTORE_BACKUP \
my_dataset.entities \
gs://my-bucket/backup/2026/07/31/entities.export
数据导出
基本写法:导出为 CSV
bq extract <表> <gs://路径>
# 导出表数据到 GCS 为 CSV
bq extract my_dataset.users \
gs://my-bucket/exports/users-*.csv
基本写法:导出为 JSON
bq extract --destination_format=NEWLINE_DELIMITED_JSON <表> <gs://路径>
# 导出为 NDJSON 格式
bq extract \
--destination_format=NEWLINE_DELIMITED_JSON \
my_dataset.users \
gs://my-bucket/exports/users.json
基本写法:导出为 Avro
bq extract --destination_format=AVRO <表> <gs://路径>
# 导出为 Avro 格式
bq extract \
--destination_format=AVRO \
--compression=SNAPPY \
my_dataset.users \
gs://my-bucket/exports/users-*.avro
基本写法:压缩导出
bq extract --compression=GZIP <表> <gs://路径>
# 导出 CSV 并使用 GZIP 压缩
bq extract \
--compression=GZIP \
my_dataset.users \
gs://my-bucket/exports/users-*.csv.gz
流式插入
基本写法:使用 insert 命令
bq insert <表> <JSON 数据>
# 流式插入单条数据
bq insert my_dataset.users \
'{"user_id":"u001","name":"Alice","age":30}'
基本写法:批量插入
bq insert <表> <文件>
# 从文件读取多行 JSON 插入
bq insert my_dataset.events events.ndjson
基本写法:忽略未知字段
bq insert --ignore_unknown_values <表> <JSON>
# 插入时忽略 schema 中没有的字段
bq insert --ignore_unknown_values \
my_dataset.users \
'{"user_id":"u002","name":"Bob","extra":"field"}'
基本写法:模板插入
bq insert --template_suffix=<后缀> <模板表> <JSON>
# 通过模板表自动创建分片表
bq insert --template_suffix=_20260731 \
my_dataset.events_template \
'{"event_id":"e001","type":"click"}'
视图与物化视图
基本写法:创建视图
bq mk --view <SQL> --use_legacy_sql=false <数据集>.<视图>
# 创建标准 SQL 视图
bq mk --view \
--use_legacy_sql=false \
my_dataset.active_users \
'SELECT * FROM my_dataset.users WHERE status = "active"'
基本写法:创建物化视图
bq mk --materialized_view <SQL> <数据集>.<视图>
# 创建物化视图聚合统计
bq mk --materialized_view \
my_dataset.user_stats \
'SELECT user_id, COUNT(*) AS cnt FROM my_dataset.events GROUP BY user_id'
基本写法:更新物化视图
bq query --use_legacy_sql=false 'ALTER MATERIALIZED VIEW <视图> SET OPTIONS(enable_refresh=true)'
# 启用物化视图自动刷新
bq query --use_legacy_sql=false \
'ALTER MATERIALIZED VIEW my_dataset.user_stats SET OPTIONS(enable_refresh=true, refresh_interval_minutes=30)'
基本写法:删除视图
bq rm -v <视图>
# 删除视图
bq rm -v my_dataset.active_users
分区表与聚簇表
基本写法:创建分区表
bq mk --table --time_partitioning_type=DAY <表> <schema>
# 按天创建分区表
bq mk --table \
--time_partitioning_type=DAY \
--time_partitioning_field=created_at \
my_dataset.events \
event_id:STRING,created_at:TIMESTAMP
基本写法:创建聚簇表
bq mk --table --clustering_fields=<字段> <表> <schema>
# 创建带聚簇列的表
bq mk --table \
--clustering_fields=user_id,event_type \
my_dataset.events \
event_id:STRING,user_id:STRING,event_type:STRING,timestamp:TIMESTAMP
基本写法:分区与聚簇组合
bq mk --table --time_partitioning_type=DAY --clustering_fields=<字段> <表> <schema>
# 创建按天分区且按 user_id 聚簇的表
bq mk --table \
--time_partitioning_type=DAY \
--time_partitioning_field=timestamp \
--clustering_fields=user_id \
my_dataset.events \
event_id:STRING,user_id:STRING,timestamp:TIMESTAMP
基本写法:查询指定分区
bq query 'SELECT * FROM <表> WHERE <分区过滤>'
# 仅查询 2026 年 7 月 31 日数据
bq query --use_legacy_sql=false \
'SELECT * FROM my_dataset.events WHERE DATE(timestamp) = "2026-07-31"'
数据处理与转换
基本写法:使用 BigQuery ML 训练模型
bq query 'CREATE MODEL <模型> OPTIONS(...) AS SELECT ...'
# 训练逻辑回归模型
bq query --use_legacy_sql=false '
CREATE OR REPLACE MODEL my_dataset.user_churn_model
OPTIONS(model_type="logistic_reg", input_label_cols=["churned"]) AS
SELECT * FROM my_dataset.user_features
'
基本写法:使用模型预测
bq query 'SELECT * FROM ML.PREDICT(MODEL <模型>, ...)'
# 使用模型预测
bq query --use_legacy_sql=false '
SELECT * FROM ML.PREDICT(MODEL my_dataset.user_churn_model,
(SELECT * FROM my_dataset.new_users))
'
基本写法:执行 DML 更新
bq query 'UPDATE <表> SET ... WHERE ...'
# 批量更新数据
bq query --use_legacy_sql=false '
UPDATE my_dataset.users
SET status = "inactive"
WHERE last_login < TIMESTAMP("2025-01-01")
'
基本写法:删除数据
bq query 'DELETE FROM <表> WHERE ...'
# 删除满足条件的数据
bq query --use_legacy_sql=false '
DELETE FROM my_dataset.users
WHERE status = "deleted"
'
调度与作业
基本写法:列出作业
bq ls -j
# 列出最近的作业
bq ls -j -n 20
基本写法:查看作业详情
bq show -j <作业ID>
# 查看指定作业状态
bq show -j job_1234567890
基本写法:取消作业
bq cancel <作业ID>
# 取消运行中的查询作业
bq cancel job_1234567890
基本写法:创建定时查询
bq query --schedule='every 24 hours' --destination_table=<表> <SQL>
# 每天定时执行汇总查询
bq query \
--schedule='every 24 hours' \
--destination_table=my_dataset.daily_stats \
--use_legacy_sql=false \
'SELECT DATE(timestamp) AS day, COUNT(*) AS cnt FROM my_dataset.events GROUP BY day'
基本写法:列出定时查询
bq ls --transfer_config
# 列出所有定时查询配置
bq ls --transfer_config --transfer_location=us
权限与共享
基本写法:添加表权限
bq add-iam-policy-binding <表> --role=<角色> --member=<成员>
# 授予用户表查询权限
bq add-iam-policy-binding \
my_dataset.users \
--role=roles/bigquery.dataViewer \
--member=user:alice@example.com
基本写法:移除表权限
bq remove-iam-policy-binding <表> --role=<角色> --member=<成员>
# 移除用户表权限
bq remove-iam-policy-binding \
my_dataset.users \
--role=roles/bigquery.dataViewer \
--member=user:alice@example.com
基本写法:授权数据集访问
bq update --source <文件> <数据集>
{
"access": [
{"role": "READER", "userByEmail": "alice@example.com"},
{"role": "WRITER", "groupBy": "data-team@example.com"}
]
}
基本写法:授权视图共享
bq update --view <SQL> <数据集>.<视图>
# 更新视图并配置授权
bq update \
--view 'SELECT user_id, name FROM my_dataset.users' \
--use_legacy_sql=false \
my_dataset.public_users
计费与优化
基本写法:查询字节数预估
bq query --dry_run <SQL>
# 干运行估算查询字节数
bq query --dry_run --use_legacy_sql=false \
'SELECT * FROM my_dataset.events WHERE DATE(timestamp) = "2026-07-31"'
基本写法:设置最大字节
bq query --maximum_bytes_billed=<字节> <SQL>
# 限制查询最大字节数
bq query \
--maximum_bytes_billed=1000000000 \
--use_legacy_sql=false \
'SELECT * FROM my_dataset.events'
基本写法:查看表存储统计
bq show --format=prettyjson <表>
# 查看表存储大小与统计
bq show --format=prettyjson my_dataset.events
基本写法:设置表过期
bq update --expiration <秒> <表>
# 设置表 30 天后过期
bq update --expiration 2592000 my_dataset.temp_data
跨云与外部数据
基本写法:创建外部表
bq mk --external_table_definition=<定义> <表>
# 创建映射到 GCS 的外部表
bq mk --external_table_definition='gs://my-bucket/data/*.csv@CSV=user_id:STRING,name:STRING' \
my_dataset.external_users
基本写法:查询 Cloud SQL
bq query 'SELECT * FROM EXTERNAL_QUERY("<连接>")'
# 通过联邦查询 Cloud SQL
bq query --use_legacy_sql=false '
SELECT * FROM EXTERNAL_QUERY("my-project.us.cloudsql-connection")
'
基本写法:BigLake 表
bq mk --table --table_type=EXTERNAL --format=PARQUET <表> <gs://路径>
# 创建 BigLake 表查询 GCS Parquet
bq mk --table \
--table_type=EXTERNAL \
--format=PARQUET \
--source_uris=gs://my-bucket/data/*.parquet \
my_dataset.biglake_table
基本写法:导出到 BigQuery Studio
bq query --destination_table=<表> --overwrite_table <SQL>
# 覆盖写结果到新表供 Studio 分析
bq query \
--destination_table=my_dataset.analysis \
--overwrite_table \
--use_legacy_sql=false \
'SELECT * FROM my_dataset.users WHERE age > 18'