FEATURED · 精选文章

如何把 Snowflake dbt 模型迁移为 BigQuery SQL:环境准备与翻译流程

发布时间 / 2026/9/15 13:30:26
来源 / 创域科博编辑部
栏目 / 资讯中心
如何把 Snowflake dbt 模型迁移为 BigQuery SQL:环境准备与翻译流程 如何把 Snowflake dbt 模型迁移为 BigQuery SQL环境准备与翻译流程【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills当你需要把一套已经在 Snowflake 上运行的 dbt 模型迁到 BigQuery 时逐个手写改写既慢又容易漏掉方言差异。skills 仓库Agent Skills for Google products and technologies中的dbt-sf-to-bq-translator技能提供了一条端到端路径用本地脚本做 Jinja 预处理与后处理中间调用 BigQuery Translation ServiceBQMS完成方言翻译最终产出符合 BigQuery 模型规范的 dbt SQL 文件。本文覆盖两件事GCP 环境的准备步骤以及批量翻译脚本的实际执行与结果核对。适用边界与技能文档一致只用于 Snowflake dbt 模型到 BigQuery 的迁移不适用于普通 BigQuery 查询或其他数据库的 SQL 迁移。技能位于 skills/cloud/dbt-sf-to-bq-translator 目录核心是 SKILL.md、翻译模式参考 和两个脚本。如果还没有拿到这个技能仓库 README 给出的安装方式是npx skills add google/skills执行时按提示选择dbt-sf-to-bq-translator。1. 准备条件Python 与 GCP 环境Python 环境翻译入口是 bulk_translate_via_gcloud.py脚本文件头声明了运行要求Python 3.11依赖pyyaml6.0dbt_translator.py用yaml解析输入目录中的.yml/.yaml文件。如果环境缺少 pyyaml先安装再运行脚本。Google Cloud 环境按 SKILL.md 的“Prerequisites Environment Setup”逐项执行# 1. 认证 CLI 会话两条都要执行 gcloud auth login gcloud auth application-default login # 2. 设置活动 GCP 项目把 {project_id} 换成你的项目 ID gcloud config set project {project_id} # 3. 启用翻译流程所需的三个服务 gcloud services enable bigquerymigration.googleapis.com storage.googleapis.com bigquery.googleapis.com # 4. 设置 BigQuery/计算区域文档推荐 us-central1 或 us gcloud config set compute/region us-central1此外还有一项需要人工确认目标项目下必须挂载了处于激活状态的 Google Cloud Billing 账号文档没有给出对应命令属于控制台侧检查项。翻译流程还需要一个 GCS 桶用于暂存输入和输出文件这会在下一步作为脚本参数传入。2. 准备输入开始一次翻译前要确定哪些值按技能文档的初始化要求开始一次新的翻译项目需要提供 6 个输入输入说明迁移项目名mig_prefix如my_migration_project用于标识本次迁移输入目录存放 Snowflake 方言 dbt.sql模型的目录输出目录BigQuery SQL 文件的落盘目录GCS 桶名暂存翻译资产的桶GCP 区域如us或eu可选元数据路径包含columns.csv或tables.csv的本地目录或.zip文件输入目录的内容会被脚本实际解析脚本遍历目录下所有.sql文件把文件名小写记为已知模型同时解析所有.yml/.yaml文件中的sources声明得到“source 名 → 表名”的映射。这两个集合用于后续把硬编码的database.schema.table路径还原成 dbt 的{{ ref(...) }}/{{ source(...) }}宏所以输入目录应当是完整的 models 目录包含 schema 定义文件。输入的.yml/.yaml文件会在流程结束时原样复制到输出目录。3. 运行批量翻译脚本入口命令路径按 SKILL.md 给出占位符含义与文档一致python3 skills/cloud/dbt-sf-to-bq-translator/scripts/bulk_translate_via_gcloud.py \ --input input_dir \ --output output_dir \ --bucket gcs_bucket \ --location region参数说明来自脚本的 argparse 定义与 SKILL.md--input别名--input-dirSnowflake SQL 文件所在目录必填--output别名--output-dirBigQuery SQL 输出目录必填--bucket别名--gcs-bucketGCS 桶名必填可带可不带gs://前缀脚本会自动去掉--locationBQMS 区域默认us。运行前必须先了解脚本的副作用这些行为可以在 dbt_translator.py 中逐条对应清理 GCS 前缀脚本会执行gcloud storage rm --recursive删除桶内{prefix}_migration_input/、{prefix}_migration_output/传了元数据时还包括{prefix}_migration_metadata/下的既有内容。其中{prefix}是输入目录名的 basename。确认这些前缀下没有存放其他数据。当前工作目录产物脚本在 CWD 创建./temp_{prefix}_input、./temp_{prefix}_output、./temp_{prefix}_metadata临时目录和{prefix}_migration_config.yaml配置文件流程结束后自动清理。建议在一个可写、不介意临时文件的目录里运行。网络与 GCS 写入预处理后的 SQL 会上传到 GCS 桶翻译结果再从 GCS 下载回本地。脚本会自动生成并在结束后删除形如下面的工作流配置源方言固定为snowflakeDialect目标为bigqueryDialectdisplayName: {prefix}-bulk-translation tasks: bulk-translation-task: type: Translation_Snowflake2BQ translationConfigDetails: gcsSourcePath: gs://bucket/prefix_migration_input/ gcsTargetPath: gs://bucket/prefix_migration_output/ sourceDialect: snowflakeDialect: {} targetDialect: bigqueryDialect: {}可选元数据与对象解析参数脚本还支持三个用于对象解析的可选参数。注意--metadata的取舍python3 skills/cloud/dbt-sf-to-bq-translator/scripts/bulk_translate_via_gcloud.py \ --input input_dir \ --output output_dir \ --bucket gcs_bucket \ --location region \ --metadata-dataset bq_dataset \ --default-database snowflake_db \ --schema-search-path SCHEMA_A,SCHEMA_B--metadata path指向含columns.csv/tables.csv的本地目录或.zip。脚本会先把与 dbt 模型/source 匹配的表名映射为占位符名、清空 catalog 列再打包成metadata.zip上传。但该路径在 BQMS v2 中已弃用传了会打印警告Warning: Direct metadata ZIP processing is deprecated in BQMS v2 API. Please run a migration assessment first and pass the dataset ID using metadata_dataset.--metadata-dataset指向包含迁移评估migration assessment元数据的 BigQuery dataset是脚本建议的替代路径--default-database对象解析用的默认 Snowflake 数据库名--schema-search-path逗号分隔的默认 schema 列表。以上任意一项存在时脚本会在生成的配置里追加对应的sourceEnv块metadataStoreDataset、defaultDatabase、schemaSearchPath。4. 脚本内部的翻译流程命令跑起来后脚本按 SKILL.md 描述的五个阶段执行了解它们有助于判断输出是否正常占位符预处理翻译前从每个文件头部剥离{{ config(...) }}块单独保存{{ source(src_name, table_name) }}替换为_DBT_SOURCE_src_name_DBTSEP_table_name_{{ ref(model_name) }}替换为_DBT_REF_model_name_其余{{ ... }}表达式变成_DBT_EXPR_N_{% ... %}控制块变成/* _DBT_BLOCK_N_ */注释。目标是让 BQMS 拿到不含 Jinja 花括号、100% 合法 Snowflake 方言的 SQL避免翻译服务报语法错误。预处理后的文件暂存到 staging 输入目录。上传并触发翻译staging 文件上传到 GCS生成上文的工作流配置然后执行gcloud bq migration-workflows create --locationregion --config-filemigration_config.yaml --no-async同步等待翻译完成。下载译文从 GCS 拉回翻译后的 GoogleSQL 文件。占位符还原与再处理翻译后按序执行——基于 AST 的config(...)重写丢弃 Snowflake 专有参数copy_grants、transient、secure清洗pre_hook/post_hook删除ALTER ICEBERG TABLE ... REFRESH、UNSET SECURE、search optimization等 BigQuery 上不合法的 hook 语句引用解析扫描 FROM/JOIN 中的硬编码database.schema.table按第一步收集的模型与 sources 映射回{{ ref(...) }}或{{ source(...) }}宏与语法审计扫描所有{{ ... }}对自定义宏和残存的 Snowflake 语法::date、::timestamp、dateadd、datesub、to_date、to_timestamp在文件内直接写# WARNING:注释边界情况清洗用括号平衡解析把::date/::timestamp改写为CAST(... AS DATE/TIMESTAMP)转换dateadd(...)和/- interval N unit在文件最顶部config 块之上加 Google 版权头。落盘按原目录结构把最终文件写入输出目录并把输入目录的全部.yml/.yaml复制到输出目录。5. 核对翻译结果脚本自身的输出就是第一层核对信号工作流结束时打印Workflow finished with code: returncode。这里的 returncode 是gcloud bq migration-workflows create的退出码非 0 说明工作流命令本身没有正常完成每个输入模型若没能在 GCS 输出中找到译文打印Warning: Translated file for rel_path not found in outputs.全部完成后打印汇总Successfully migrated n SQL files and copied m YAML files to output_dir!。对照输入目录的.sql数量核对n对照.yml/.yaml数量核对m。然后抽查输出文件正确结构应与 dbt_migration_patterns.md 的模板一致# Copyright 2026 Google. This software is provided as-is, without warranty or # representation for any use or purpose. Your use of it is subject to your # agreement with Google. {{ config(...) }} WITH raw_json AS ( SELECT a.data as json_data, a._extracted_at, SAFE_CAST(JSON_EXTRACT_SCALAR(a.data, $.id) AS INT64) as primary_id, row_number() over (partition by JSON_EXTRACT_SCALAR(a.data, $.id) order by a._extracted_at desc) as rn FROM {{ source(..., ...) }} as a {% if is_incremental() %} WHERE _extracted_at (SELECT MAX(_extracted_at) FROM {{ this }}) {% endif %} QUALIFY rn 1 ), ...逐项确认版权头位于文件最顶部之后才是{{ config(...) }}config(...)中已无copy_grants、transient、securehook 里不再有ALTER ICEBERG TABLE ... REFRESH、UNSET SECURE等语句文件顶部的# WARNING:注释行是审计结果逐条处理自定义宏需要人工确认其 BigQuery 等价写法Snowflake 语法残留需要手工改写{{ ref(...) }}、{{ source(...) }}、{% if is_incremental() %}等 Jinja 结构被保留is_incremental()块保持可用。输出文件应符合的方言标准以下规则来自技能文档的 Mandates 章节可作为人工复核清单。JSON 取值一律用CAST(JSON_EXTRACT_SCALAR(json_column, $.path) AS TYPE)不用 Snowflake 冒号记法类型对应关系见参考文档的对照表示例值均来自该文档特性Snowflake 源BigQuery 目标JSON 路径data:user:id::intSAFE_CAST(JSON_EXTRACT_SCALAR(data, $.user.id) AS INT64)布尔data:active::booleanSAFE_CAST(JSON_EXTRACT_SCALAR(data, $.active) AS BOOL)截断LEFT(comment, 2000)SUBSTR(comment, 1, 2000)搜索comment LIKE %urgent%LOWER(comment) LIKE %urgent%数组展开LATERAL FLATTEN(input data:tags)CROSS JOIN UNNEST(JSON_EXTRACT_ARRAY(data, $.tags))日期加法DATEADD(hour, 1, date)DATE_ADD(SAFE_CAST(date AS DATETIME), INTERVAL 1 HOUR)其他要点类型安全join/filter 两侧类型不同时对两边都做CAST系统 ID 用INT64占位列写CAST(NULL AS TYPE)去重源模型需要按主键去重时在基础 CTE 里加row_number() over (partition by [PRIMARY_KEY] order by [TIMESTAMP] desc) as rn并对该 CTE 应用qualify rn 1关联连接自定义字段/属性表时用LEFT JOIN避免丢记录post_hook 中的比较WHERE子句显式转型例如把where t.ticket_id stage.id写成where SAFE_CAST(t.ticket_id AS STRING) SAFE_CAST(stage.id AS STRING)。6. 限制与收尾--metadata直接传 ZIP 的路径在 BQMS v2 已弃用脚本会打印警告文档建议先做一次 migration assessment再用--metadata-dataset传 dataset ID脚本会删除桶内{prefix}_migration_*前缀下的既有对象复用同一个桶时注意前缀冲突技能文档还要求一个收尾动作翻译结果先经人工确认把确认中提出的问题在输出文件里改完才算完成交接。按技能约定翻译产物放在migration_plan/[mig_prefix]/translated_models/下进度记录在migration_plan/[mig_prefix]/tasks.md中由人工监督者跟踪。当汇总行显示迁移的文件数与输入模型数一致、无not found in outputs警告、且抽查文件通过上述结构核对后这批模型就可以作为 BigQuery dbt 项目的起点进入后续构建验证了。【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻