Metabase Transforms 完全指南:在数据库内持久化 ETL 结果并复用于查询
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
Transforms(转换)是 Metabase Data Studio 中承担 "ETL" 的 "T" 的核心机制:你可以用 SQL、查询构建器或 Python 编写查询,Metabase 会执行它、在你的目标数据库中创建一张持久化表,并把这张表同步回 Metabase,使其能够作为问题(Questions)或其他 Transforms 的数据源。读完本文,你将掌握 Transforms 的启用方式、创建与调度流程、增量同步与 merge key 机制、依赖管理、版本化同步,以及其背后的应用数据库模型与驱动能力声明等源码级实现细节。
一、Transforms 是什么:概念模型
Transforms 用于对你的数据做预处理、清洗、表连接(join)、指标预计算等工作。其工作流程如下:
- Transforms是查询(用 SQL 或查询构建器创建)或 Python 脚本,它们写回你的数据库并创建一张新的持久化表。适合用于清洗、连接、预聚合数据。
- Transforms 通过tags(标签)与jobs(作业)进行调度与组织:
- 给 Transforms 分配标签(如 daily、hourly)来分组;
- 一个 job 按调度(例如每天午夜)运行,并执行所有被分配了特定标签的 Transforms。
- 每一次 Transforms 的执行都是一个run。run 会用最新结果替换目标表,你可以查看 run 历史来监控成功或失败。
- 你可以inspect(检查)一个 Transform 来分析其数据流、join 行为与列分布(详见 Transform inspector)。
源码印证:从源码结构看,Transform 的完整数据模型定义在 src/metabase/transforms/schema.clj 中。其中::transform模式(第 104–124 行)声明了应用数据库中:transform表的每一列,包括:source(查询来源)、:target(目标表)、:last_checkpoint_value(增量检查点)、:target_table_id、:table_dependencies(表依赖)等字段——文档中提到的 run、检查点、依赖等概念都能在数据库模型中一一对应。同样地,::transform-run(第 262–282 行)、::transform-job(第 185–197 行)、::transform-tag(第 317–325 行)等模式分别对应 run 记录、调度作业与标签的持久化结构。
二、支持 Transforms 的数据库
当前 Metabase 可以在以下数据库上创建 Transforms:
- BigQuery
- ClickHouse(仅 ClickHouse Cloud)
- MySQL/MariaDB
- PostgreSQL
- Redshift
- Snowflake
- SQL Server
启用 Database routing(数据库路由) 的数据库,以及 Metabase 示例数据库(Sample Database),不能创建 Transforms。
由于 Transforms 会在你的数据库中创建表,连接所用的数据库用户必须具有相应权限。参见 Database users, roles, and privileges。建议为数据库配置 Writable connection(可写连接)。
源码印证:每个驱动通过 features 映射声明自己是否支持 transforms。例如 PostgreSQL 驱动在 src/metabase/driver/postgres.clj 中声明了:transforms/index-ddl、:transforms/python、:transforms/table三个能力位;MySQL 驱动在 src/metabase/driver/mysql.clj 声明了:transforms/table;而社区驱动模块(modules/drivers)中的 BigQuery、ClickHouse、Redshift、Snowflake、SQL Server 驱动(如 modules/drivers/snowflake/src/metabase/driver/snowflake.clj、modules/drivers/clickhouse/src/metabase/driver/clickhouse.clj)同样声明了:transforms/table能力,与文档列出的七种支持数据库完全一致。
三、Transforms 的两种类型
Metabase 支持两种类型的 Transforms:
- 基于查询的 Transforms(query-based):用 SQL 或 Metabase 查询构建器编写,运行在你的数据库中。工作原理详见 How query-based transforms work。
- Python Transforms:用 Python 编写,运行在专用的执行环境中。工作原理详见 How Python transforms work。
源码印证:src/metabase/transforms/feature_gating.clj 中的enabled-source-types函数揭示了三种来源类型的开关逻辑:当查询 Transforms 功能启用时返回"native"与"mbql"(分别对应 SQL 与查询构建器),当 Python Transforms 功能启用时追加"python"。在数据模型层,schema.clj 中的::transform-source模式按:type字段多态分发为:query(携带:query与可选的:source-incremental-strategy)和:python(携带:source-database、:source-tables、:body脚本体)两个分支。
这些功能开关由高级特性(premium features)控制。在 src/metabase/premium_features/token_check.clj 中:
query-transforms-enabled?要求实例具备:transforms-basic特性,且全局设置:transforms-enabled为 true;python-transforms-enabled?额外要求:transforms-python特性;any-transforms-enabled?则是两者的"或"。
这与后文"自托管部署"章节中 Basic / Advanced 两个档位的划分相互印证。
四、Transforms 的权限模型
Transforms 的权限配置取决于你的订阅计划:
- Metabase Open Source / Starter:只有管理员(Admin)能看到并运行 Transforms。
- Metabase Pro / Enterprise提供额外的权限控制:一个供非管理员访问 Transforms 的特殊 Data Analysts(数据分析师) 组,以及针对每个数据库的细粒度 Transform 权限:
- 要看到实例上的 Transforms 列表,用户必须能访问 Data Studio,即须为 Admin 或特殊 Data Analyst 组 的成员;
- 要执行某数据库上的 Transforms,用户须为 Admin 或 Data Analyst 组成员,并且还要拥有该数据库的 Transform permissions(转换权限)。
五、在自托管 Metabase 上配置 Transforms
如果你自行部署 Metabase,让 Transforms 跑起来的路径如下:
- 确认你的计划。Basic transforms(基于查询的)包含在自托管 Metabase 中;Advanced transforms —— Python Transforms、transform inspector 与 writable connections —— 需要自托管 Pro 或 Enterprise 计划并附带 Advanced transforms 附加组件。
- 连接一个可写的数据库。Transforms 会在数据库中创建和替换表,因此数据库用户需要 create、drop 与写权限(参见 Database users, roles, and privileges)。为了更干净的隔离,建议把 Transform 指向一个 writable connection。注意只有部分数据库 支持 transforms。
- Python Transforms 需要配置 runner。查询类 Transforms 不需要额外组件——它们直接在数据库内运行。Python Transforms 运行在独立的执行环境中,你需要把 Metabase 指向一个由 S3 兼容存储(AWS S3、MinIO 等)支撑的 自托管 Python runner。
- 在 Data Studio 中启用 Transforms。
- 创建并运行一个 Transform。创建基于查询的 Transform 或 Python Transform,手动运行一次,在Runs下检查结果。跑通之后,再用 jobs 进行调度。
六、Transforms 与 Models 的区别
Transforms 与开启了 model persistence(模型持久化)的 models 类似,但有关键差异:
- Transforms 只能由拥有 transform 权限的分析师创建;而 models 可以由任何有权限在该数据源上创建查询的人创建(但只有管理员能在实例上启用 model persistence)。
- Transforms 可以自选目标 schema 与表;model persistence 会自建 schema 与表。
- Transforms 支持的数据库比 model persistence 更多。
- Transforms 支持用 Python 创建。
实践建议:用 models 让非管理员在 Metabase 内创建自己的数据集并添加字段描述、语义类型等上下文;用 transforms 在数据库中创建持久化数据集并跨 Metabase 复用。文档同时指出,在 Metabase 未来版本中,model persistence 将逐步被 transforms 取代。在 Pro/Enterprise 计划上,还可以批量将 models 转换为 transforms,见 Convert models to transforms。
七、启用 Transforms
在开始编写 Transforms 之前,需要先在实例中启用 Transforms。
如果你使用的是 Metabase Cloud 计划,只有以 Metabase Store 管理员邮箱登录的人(而不仅仅是 Metabase 实例管理员)才能启用 basic transforms,因为在 Metabase Cloud 上 Transforms 按运行次数计费。
启用步骤:
- 点击 Metabase 右上角的grid 图标,选择Data Studio进入 Data Studio。
- 在 Data Studio 中,点击右侧边栏的Transforms。
- 如果实例尚未启用 Transforms,会看到启用提示,直接点击启用即可。
启用 Transforms 之后,即可配置权限并开始创建 Transforms。
八、查看所有 Transforms
路径:Data Studio > Transforms(权限要求见权限模型)。
- 点击右上角grid 图标,进入Data Studio。
- 在左侧边栏选择Transforms,即可看到实例上的全部 Transforms。
九、创建一个 Transform
路径:Data Studio > Transforms。
如果你使用 remote sync 且实例处于 "read-only"(只读)同步模式,将无法创建 Transforms。
创建步骤:
启用 Transforms。
点击右上角grid 图标,进入Data Studio。
在左侧边栏选择Transforms。
点击+ New并为 Transform 选择来源。
你可以用 Metabase 的图形查询构建器、SQL 或 Python 来编写。查询类细节见 query-based transforms,Python 类见 Python transforms。
如果选择Copy of a saved question(已保存问题的副本)作为来源,可以把一个现有 Metabase 问题(SQL 问题或查询构建器问题)的查询复制进 Transform。Metabase 只会_复制_该问题的查询,之后对原问题的修改不会影响 Transform 的查询。
编写 Transform 的查询或脚本。编写时可以引用其他 Transform 的目标表。
- 如果写的是 SQL Transform,变量_必须_包裹在可选块(
[[ ]])中,或给定默认值,详见 variables in SQL transforms。 - 如果 Metabot 已启用,可以用 Metabot 生成代码。
- 如果写的是 SQL Transform,变量_必须_包裹在可选块(
点击右上角Save,填写 Transform 信息:
- Name(名称,必填):Transform 的名称。
- Schema(模式,必填):目标 schema。它可以与源表的 schema 不同;在此输入框中键入新名称即可创建新 schema。注意 Transform 只能在_同一个数据库内_进行,不能从一个数据库写到另一个。
- Table name(表名,必填):目标表名。Metabase 会把 Transform 结果写入该表,随后同步该表到 Metabase。
- Folder(文件夹,可选):Transform 所在的文件夹,点击字段可选择或新建。
- Incremental transformation(增量转换,可选):参见 Incremental query-based transforms 或 Incremental Python transforms。
保存后,可选地为 Transform 分配标签。标签用于让 jobs 按调度运行 Transforms。
源码印证:保存表单中的 Schema / Table name 对应数据模型 schema.clj 中的::transform-target模式:完整重写目标使用table类型({:type "table" :schema ... :name ...}),增量目标则使用table-incremental类型并额外携带:target-incremental-strategy(append或merge两种策略),这与前端设置表单中"增量转换"选项一一对应。执行入口在 src/metabase/transforms/execute.clj:execute!先通过resolve-target解析目标(包括挂接声明的索引,并一次性决定本次是否为"全量增量运行"),随后委托给transforms.i/execute!的:query方法(由metabase.transforms.query-impl命名空间提供实现)完成"执行查询 + 同步目标表"。
十、使用 Metabot 为 Transforms 生成代码
Transform 的代码生成需要 AI features(AI 功能)。
可以让 Metabot 生成新的 SQL 或 Python Transform,也可以编辑现有 Transform:
进入Data Studio > Transforms;如果让 Metabot 编辑现有 Transform,先导航到该 Transform。
在 Transforms 视图中点击右上角的 Metabot 图标。
描述你想要 Metabot 编写的 Transform。可以指明想要哪种类型(Python 或 SQL),并通过 @-mention 指定数据源来帮助 Metabot 理解需求。
Metabot 会为自己创建一份待办清单(展示其思考过程),然后逐条处理。
如果要求 Metabot 创建新 Transform,在聊天窗口中审查它给出的代码,然后点击代码片段下方的 "Create"。
之后可以继续与 Metabot 协作打磨代码:Metabot 会建议代码修改,并给出接受或拒绝修改的选项。
十一、编辑一个 Transform
路径:Data Studio > Transforms。
可以编辑 Transform 的名称与描述、查询/脚本、目标表与增量设置。即使 Transform 已经运行过或已被调度,也依然可以编辑。使用 remote sync 且实例处于 "read-only" 同步模式时无法编辑。
编辑查询或脚本
路径:Data Studio > Transforms > Definition(权限要求见权限模型)。
- 进入Data Studio > Transforms。
- 找到要编辑的 Transform,点击 Transform 定义上方的Edit definition。
- 编辑查询或脚本(可借助 Metabot)。
修改查询或脚本后,下一次运行(手动或调度)将使用更新后的查询并把结果写入目标表。如果表结构(列)发生了变化,且已有问题在查询这张表,那些问题可能会损坏。例如:新的 Transform 查询不再包含某个下游问题依赖的列,该问题就会损坏。
修改目标表
路径:Data Studio > Transforms > Settings。
在 Transform 的Settings标签页点击Change target即可更换目标表,需要选择保留还是删除旧目标表。删除不可撤销。
**建立在旧目标上的问题_不会_迁移到新目标表。**如果删除旧目标表,所有使用旧目标表的问题都会损坏;如果保留旧目标表,基于它的问题不会损坏,但也不会使用新目标表,从而变得过期。
十二、运行一个 Transform
Transform 可以手动运行,也可以用标签与作业调度:
- 手动运行:进入Data Studio > Transforms > Runs(Transform 页面),点击Run。
- 调度运行:给 Transform 分配一个或多个标签,然后创建挑选这些标签的调度作业(scheduled job)。
首次运行会创建并同步该 Transform 生成的表,之后就可以编辑该表的元数据与权限。后续运行会删除并重建该表——除非使用增量 Transforms。
你可以在 Transform 页面或 Runs 视图中查看最近一次运行的时间与状态,运行时间以系统时区显示。Python Transforms 还可以看到执行日志。
源码印证:每次运行对应的TransformRun记录包含run_method(手动/调度)、status、start_time/end_time、message、user_id,以及增量运行专用的checkpoint_filter_field_id、checkpoint_lo_value、checkpoint_hi_value字段(见 schema.clj)。对于增量 Transform,"上次处理到的检查点值"正是以字符串形式持久化在 Transform 的last_checkpoint_value列中,与下文"重新处理全部数据"的语义相符。
十三、检查(Inspect)一个 Transform
路径:Data Studio > Transforms > [Transform 名称] > Inspect。
Transform inspector 需要 Advanced transforms 附加组件。
Transform inspector 让你深入探查 Transform 的输入与输出。
十四、Transform 依赖关系
路径:Data Studio > Transforms > Dependencies。
Transform 查询可以使用其他 Transform 的数据,查询类 Transform 还可以引用 Metabase 的 questions 与 models。例如:一个 Transform 读取raw_events表并写入stg_events表,另一个 Transform 读取stg_events并写入events表。
Metabase 会跟踪 Transform 依赖,并按合理顺序执行:例如 Transform B 依赖 Transform A 创建的表,则 Metabase 先运行 A 再运行 B。
在 Pro 或 Enterprise 计划上,可以通过Data Studio > Transforms的Dependencies标签页查看依赖关系图。如果某个作业包含依赖了其他 Transform 产物的 Transform,则该作业会运行所有带标签的 Transforms,外加所有尚未处于最新状态的依赖项。
源码印证:依赖解析逻辑位于 src/metabase/transforms/dag.clj 与 src/metabase/transforms/coordinated_run.clj;数据模型中 Transform 的table_dependencies列(schema.clj)持久化了每张被引用的源表,而TransformDagRun记录(schema.clj)则以"以某个 Transform 为源、向上/向下展开"的方向(:direction)记录依赖子图的协调运行状态。从源码结构看,"作业连同其未更新依赖一起运行"正是由这些 DAG 协调运行机制实现的。
十五、增量 Transforms
路径:Data Studio > Transforms > Settings。
增量 Transform 只处理自上次运行以来新增的数据。例如:每天有新交易数据流入,Transform 每晚运行;每次运行只处理前一天运行之后新增的行。
默认情况下,Metabase 把这些行**追加(append)**到目标表。如果源表会随时间记录同一记录的变更,可以通过设置 merge key(合并键) 使 Metabase 更新现有行而非添加重复行。此时,checkpoint(检查点)字段决定哪些行算"新",merge key 决定 Metabase 是追加这些行还是更新匹配行。
前置条件
- 数据中必须有一列可供 Metabase 检查新值以判定哪些数据是新的,称为Checkpoint(检查点)列。
- 检查点列的值必须递增,如自增 ID 或时间戳列。Metabase 通过查找_大于_已写入检查点值的值来判断"新"数据。
- Schema 必须稳定,即表结构在各次运行之间不会变化。
源码印证:在 schema.clj 中,::checkpoint-strategy声明了检查点策略:{:type "checkpoint" :checkpoint-filter-field-id ...},并支持一个可选的:lookback(回看窗口)配置——"每次运行重读检查点之前value个unit时间跨度内的源行,从而迟到但早于水位线的行仍能被捕获",且仅支持时间型检查点列。这为文档所述"大于已写入检查点值"的语义提供了一个补充能力:处理迟到数据。
十五点一 添加 merge key 以 upsert 行
默认情况下,Metabase 输出 Transform 时是追加行。添加 merge key 后可以改为 upsert(更新或追加)。
为什么需要 merge key:有些源表在记录每次变更时都会产生新行。例如同一订单先以created出现一次、再以paid出现一次、再以shipped出现一次。如果追加这些行,同一订单就有三行——也许这正是你想要的。但如果你想就地更新这些记录,可以选一列(如订单 ID 列)作为 merge key。设置了 merge key 后,Metabase 会先尝试更新匹配键的现有记录;找不到匹配时再追加新记录。
添加 merge key:
- 进入Data Studio > Transforms中的 Transform 页面。
- 切换到Settings标签页,打开Only process new data(只处理新数据)。
- 在Merge key中选择标识记录的列。如果目标表已存在,可以从列列表中选择;如果 Transform 尚未运行过、表还不存在,则需要键入每个列名并按逗号或回车。此时键入的应是数据库中的列名(可能与列表里显示的显示名不同)。
merge key 指向的是_目标_表(Transform 输出的列)中的列,而不是_源_表中的列。如果标识一条记录需要多列组合(如id加region),就选择多个列作为 merge key。
merge key 需要一个每次写入都递增的检查点字段(如updated_at时间戳),否则 Transform 永远看不到变化。
源码印证:merge key 的数据结构定义在 schema.clj:::merge-key-column允许携带已解析的:field-id(目标列已知时),或在目标表尚不存在时退化为:name引用;::merge-config为{:type "merge" :unique-key [...]},与::append-config({:type "append"})一起构成::target-incremental-strategy的两种分支。"目标表尚不存在时需手动键入列名"这一 UI 行为,正对应 schema 中:name与:field-id二选一的降级设计。
十五点二 重新处理全部数据以重建目标表
增量 Transform 运行过后,其Settings标签页会显示Last processed [checkpoint field],后面跟着 Metabase 已写入的最高检查点值。该值就是 Metabase 断点续传的依据——每次运行只处理它之后的行。
要清除该值并重新处理所有行,点击Reprocess all data。下一次运行时将从零重建目标表,处理每一行而不仅是新增行。点击后不会立即开始运行;需要手动运行 Transform,或等待下一次调度运行。
修改检查点字段同样会重置存储的值,因此换用另一个字段做检查点后,Transform 的下一次运行也会从零重建。
源码印证:"Last processed checkpoint" 展示的就是 Transform 记录中的last_checkpoint_value列(schema.clj);"Reprocess all data" 与该列被清空后、下一次运行按全量处理的行为,与执行入口resolve-target中计算的:full-incremental-run?决策(execute.clj)相对应——该决策在运行开始时基于数据库状态一次性做出,并在整个运行期间保持稳定。
十五点三 让 Transform 变为增量
增量 Transform 在查询类与 Python 类上的工作方式不同,详见 incremental query transforms 与 incremental Python transforms。
十六、Transforms 的版本化(Remote Sync)
路径:Admin > General > Remote sync。
可以通过 Remote Sync 将 Transforms 检入 git。启用 Transform 同步后,Metabase 会把 Transforms 序列化为 YAML 文件并推送到你指定的 GitHub 仓库分支。
启用 git 同步:
- 点击右上角grid 图标进入Admin。
- 在General标签页的左侧边栏选择Remote sync。
- 按 Set up Remote Sync 的步骤操作,并打开 "Transforms" 同步开关。
注意:该设置只控制 Transforms 是否被检_入_ git 仓库,_不_影响实例在只读模式下的行为。如果实例处于只读模式,你将无法创建或编辑 Transforms。
十七、小结与延伸阅读
Transforms 把 Metabase 从一个纯粹的 BI 查询工具扩展为"在数据库内执行持久化 ETL"的完整数据工作流平台:
- 执行面:SQL / 查询构建器在数据库内执行,Python 脚本在独立 runner 中执行,结果统一写回目标数据库并同步回 Metabase;
- 调度面:tags + jobs 按调度批量触发,依赖 DAG 保证执行顺序,runs 提供可观测的历史与日志;
- 增量面:checkpoint 决定"什么是新数据",merge key 决定"追加还是 upsert",
last_checkpoint_value持久化断点,支持"重新处理全部数据"重建目标表; - 治理面:按数据库的细粒度 Transform 权限、Special Data Analyst 组,以及通过 Remote Sync 把 Transforms 序列化为 YAML 纳入 git 管理。
建议进一步阅读:
- 基于查询的 Transforms
- Python Transforms
- Python runner 自托管
- Jobs 与 Runs
- Transform inspector
- Basic 与 Advanced transforms 附加组件
- Data Studio 总览
- 核心实现:src/metabase/transforms、src/metabase/transforms_base、驱动能力声明 src/metabase/driver/postgres.clj 与 modules/drivers
【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考