跳转至

BigQuery 连接器

BigQuery 通过 jobs.query REST API 访问, 用服务账号认证 —— 不需要驱动,也不需要 SDK。用服务账号的私钥签一个短期断言, 换成 OAuth access token,token 会缓存起来,快过期时自动重新获取。

这个 API 每个请求都是独立的:默认数据集随每个请求一起发送,USE 不会在语句之间保留。 由 exec-bigquery 这个 feature 控制。

实验阶段

完整的对拍语料库已对真实项目跑通 —— 216 个用例全过,没有跳过任何一个, 另有一组冒烟测试覆盖各类型解码与多页结果。之所以仍标记为实验阶段而非预览: 它还没进每日 CI 矩阵,而且结果是按行返回的,走的不是列式读取。参见 连接器成熟度

连接配置

datasources:
  bigquery:
    type: bigquery
    project: ${BIGQUERY_PROJECT}       # GCP 项目 ID(也可写 catalog:)
    dataset: ${BIGQUERY_DATASET}       # 默认数据集(也可写 database:)
    credentials_path: ~/.gcp/service-account.json
    location: US                       # 可选,例如 US / EU
    billing_project_id: quota-project  # 可选,默认取 project

字段名与 datus-bigquery adapter 保持一致,所以同一份 datasource 配置 可以同时给 datus-agent 和 Dosi 用。

参数

字段 类型 必填 默认值 说明
type string bigquery
project string GCP 项目 ID。也可以写成 catalog:(Datus 对这一层的叫法),两种写法只能选一个。
dataset string 默认数据集,这样 SQL 里只写表名也能解析。也可以写成 database:,同样只能选一个。
credentials_path path 三者选一 服务账号 JSON 密钥文件的路径。
credentials_info string 三者选一 服务账号 JSON 的内容本身。建议用 ${VAR} —— 规则和 password 一样,包括明文告警。
credentials_base64 string 三者选一 同一份 JSON 的 base64 编码,适合会破坏换行的密钥管理系统。
location string API 默认值 任务所在区域(USEUasia-northeast1 等)。如果数据集不在 API 的默认区域,这个必须填。
billing_project_id string project 任务的计费项目,任务也在这个项目里创建。
default bool false 连接配置

这个连接器会解析但忽略的字段:hostportusernamepassworduri(直接报错)、schema也会报错,原因见下)、sslmodesslrootcertwarehouserolearrow_flight_portcompat_mode

认证

给服务账号创建一个密钥,然后让 credentials_path: 指向它:

$ gcloud iam service-accounts keys create ~/.gcp/service-account.json \
    --iam-account=<name>@<project>.iam.gserviceaccount.com

这个账号需要在计费项目上有 bigquery.jobs.create 权限,以及对数据的读权限。 断言的签发者、受众和 scope 都从密钥文件里推导出来,不需要额外配置。

如果不想把密钥放在文件系统里,可以直接传内容:

credentials_info: ${BIGQUERY_CREDENTIALS_INFO}

三个凭据字段只能配一个。配了两个就意味着有两个候选密钥, 而默认挑一个正是"用错身份连上去"的由来。

不支持应用默认凭据(ADC)。 gcloud auth application-default login 写出来的文件是 authorized_user 类型,它需要 refresh_token 授权流程,而不是服务账号的 JWT 流程; 连接器会直接指出这一点,而不是让你后面撞上一个看不懂的签名错误。

两个项目,不是一个

billing_project_id 是任务运行和计费的地方,project 是表所在的地方。 两者经常相同,但服务账号常常只能在自己的项目里创建任务,却要读另一个项目的数据。 如果这两个搞反了,报的是创建任务时的权限错误,而不是找不到表:

Access Denied: Project <p>: User does not have bigquery.jobs.create permission

已知限制

  • 没有 schema 这一层。 BigQuery 的命名空间是 project → dataset, dataset 底下没有更细的层级,所以写了 schema: 会直接报错,而不是被悄悄忽略。 把数据集写进 dataset:(或 database:)。
  • 只有行式路径。 结果以 JSON 返回,再由公共的归一化层转成 Arrow。 列式的 Storage Read API 还没有接入,它被归到了计划中的通用 exec-adbc 通道里。
  • DDL 里的 PRIMARY KEYFOREIGN KEY 必须声明成 NOT ENFORCED, 而且 BigQuery 没有 AUTO_INCREMENTSERIAL、存储 ENGINEDISTRIBUTED BY 子句 —— 如果你通过 --execute 跑初始化脚本,这几条会有影响。

时间和数值类型不用你操心。这个 API 报的是它的旧版类型名 (INTEGERFLOATBOOLEAN,而不是你在 DDL 里写的 GoogleSQL 类型 INT64FLOAT64BOOL),TIMESTAMP 用科学计数法表示 epoch 秒, DATETIMETIME 的小数部分会补齐到微秒;这些都会被归一化成其他连接器 一致的形式。NUMERICBIGNUMERIC 里超出浮点精度的值会保留为精确的 十进制文本。

本地验证连接

$ dosi query --model model.yaml \
    --metrics revenue --group-by orders.status --execute --connection bigquery

认证有问题时会看到 HTTP 401,或者 token 端点返回的错误, 里面带着 Google 自己的提示,足以区分"密钥被吊销"和"项目填错"。

排错

报错 原因与处理
connection "x" (bigquery) needs project project:(或 catalog:)。
connection "x" (bigquery) has no credentials credentials_path / credentials_info / credentials_base64 一个都没配。不会去找 ADC。
datasource "x" (bigquery) sets more than one of credentials_path, … 只保留一个。
connection "x": credentials are of type "authorized_user", not "service_account" 这是 gcloud auth application-default login 生成的 ADC 文件。请改用服务账号密钥。
connection "x": credentials are not valid JSON / lack client_email / lack private_key 不是服务账号密钥文件,或者复制时被截断了。
connection "x": bad service-account private key private_key 字段不是 PKCS#8 PEM。Google 签发的密钥不会这样,出现这个说明 JSON 被改过。
datasource "x": credentials_info must be a string 它被写成了嵌套的 YAML。请改用 ${VAR}credentials_path。报错时不会回显该字段的值,密钥不会进日志。
datasource "x": bigquery has no schema level below a dataset 去掉 schema:
datasource "x": sets both "project" and "catalog"(或 "dataset"/"database" 这两组互为别名,各保留一个。
token endpoint returned no access_token: <msg> 时钟偏差超出了断言的有效窗口,或密钥已被禁用/删除,或服务账号没有 BigQuery scope。
Access Denied: … does not have bigquery.jobs.create permission billing_project_id(或 project)指向了一个该账号无法创建任务的项目。
Not found: Dataset <p>:<d> dataset 写错了,或者数据集在另一个 location
BigQuery job did not finish within the poll budget 查询超过了五分钟。请缩小范围。
bad BigQuery JSON: <e> 端点返回了非预期内容,通常是代理或故障页面。

参考链接