<@U088WCP3B4P> elementary能收集dbt source freshness的数...
# ask-elementary-ai
l
@kapa.ai elementary能收集dbt source freshness的数据到数据库里吗?
k
A message from kapa.ai
是的,Elementary 可以将 dbt source freshness 的结果收集到数据库中,但具体方式取决于你使用的 dbt 版本和运行环境: - **dbt 1.8 及以上版本**:你只需在
dbt_project.yml
文件中添加如下配置:
Copy code
yaml   flags:     source_freshness_run_project_hooks: True
这样,Elementary 就会像收集其他测试结果一样,自动收集 source freshness 的结果,无需额外操作。 - **dbt 1.8 以下版本**:需要手动执行以下命令来上传 source freshness 结果:
Copy code
edr run-operation upload-source-freshness --project-dir <你的项目路径>
这个命令需要在运行
dbt source freshness
之后、执行
edr monitor
之前运行,并且要在同一台机器上执行(因为需要读取
sources.json
文件)<br> [详细说明见官方文档](https://docs.elementary-data.com/oss/guides/collect-dbt-source-freshness)。 - **dbt Cloud 用户**:目前 Elementary 无法直接从 dbt Cloud 自动收集 source freshness 结果,但有用户分享了通过 API 拉取
sources.json
并手动上传的变通方法,具体可参考[社区建议](https://elementary-community.slack.com/archives/C02CTC89LAX/p1688113609829869)。 总结:Elementary 支持将 dbt source freshness 的数据收集到数据库,但具体操作方式需根据 dbt 版本和运行环境调整。[参考文档](https://docs.elementary-data.com/oss/guides/collect-dbt-source-freshness)
l
@kapa.ai 开启了这个source_freshness_run_project_hooks: True之后,是得等dbt source freshness运行完之后数据才会收集到数据库?
k
A message from kapa.ai
是的,开启
source_freshness_run_project_hooks: True
之后,只有在
dbt source freshness
命令执行完成后,Elementary 才会自动收集并上传 source freshness 的结果到数据库。这是因为 dbt 1.8 及以上版本支持在 source freshness 命令结束时触发 on-run-end hook,Elementary 正是通过这个机制来收集数据的。也就是说,数据的收集是在 source freshness 运行完毕后才发生的,而不是在运行过程中实时上传的 [官方文档说明](https://docs.elementary-data.com/oss/guides/collect-dbt-source-freshness)。
l
@kapa.ai dbt源新鲜度配置你可以给我配一个模板看看吗
k
A message from kapa.ai
当然可以,以下是 dbt 源(source)新鲜度(freshness)配置的模板示例,你可以将其放在你的 source 定义的 yml 文件(如 schema.yml)中:
Copy code
yaml version: 2  sources:   - name: my_source     tables:       - name: my_table         freshness:           warn_after: {count: 1, period: hour}           error_after: {count: 24, period: hour}         loaded_at_field: updated_at
-
warn_after
和
error_after
分别定义了多久没有新数据时发出警告和错误。 -
loaded_at_field
是你用来判断数据新鲜度的时间戳字段。 你可以根据实际表结构和业务需求调整这些参数。更多细节可以参考 [dbt 官方文档](https://docs.getdbt.com/reference/resource-properties/freshness) 以及 Elementary 的相关说明 [参考](https://docs.elementary-data.com/oss/guides/collect-dbt-source-freshness)。
l
@kapa.ai 有过滤配置吗?比如说有些大表,我是按时间分区的,如果全表扫描,就会很久
k
A message from kapa.ai
是的,dbt source freshness 支持过滤配置,可以通过
filter
字段来限制新鲜度检查的数据范围,避免全表扫描,尤其适用于大表和分区表。 你可以在 source 的 freshness 配置中添加 `filter`,例如:
Copy code
yaml sources:   - name: my_source     tables:       - name: my_table         freshness:           warn_after: {count: 1, period: hour}           error_after: {count: 24, period: hour}           filter: partition_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 3 DAY)         loaded_at_field: partition_date
这样配置后,dbt 只会检查最近 3 天的数据分区,显著减少扫描的数据量和运行时间。 这个用法在 Elementary 社区也有用户提到,并给出了类似的 filter 配置示例 [相关讨论](https://slack.com/archives/C02CTC89LAX/p1695821762222709)。
l
@kapa.ai 我的分区字段是分成三个,year、month、day,帮我重写一下
k
A message from kapa.ai
如果你的分区字段是 year、month、day 三个字段,你可以在 dbt source freshness 的 filter 里拼接成日期进行过滤。根据 Elementary 社区的建议,你可以这样写:
Copy code
yaml sources:   - name: my_source     tables:       - name: my_table         freshness:           warn_after: {count: 1, period: hour}           error_after: {count: 24, period: hour}           filter: DATE(CONCAT(year, '-', month, '-', day)) >= DATE_SUB(CURRENT_DATE(), INTERVAL 3 DAY)         loaded_at_field: DATE(CONCAT(year, '-', month, '-', day))
这样配置后,dbt 只会检查最近 3 天的数据分区,避免全表扫描。拼接方式和 filter 语法可以根据你的数据仓库(如 BigQuery、Snowflake 等)适当调整,但思路是一致的。 如果你需要将 year、month、day 转为 timestamp 类型,也可以参考 Elementary 社区的做法,例如在 Snowflake 下:
Copy code
yaml loaded_at_field: to_timestamp(year || '-' || month || '-' || day)
[参考社区讨论](https://slack.com/archives/C02CTC89LAX/p1708500107119859)
l
@kapa.ai这样配置不对,报错了 (.venv) PS E:\code\Python\hooray-dbt\dbt_snowflake> dbt source freshness 100417 Running with dbt=1.7.18 100418 Registered adapter: snowflake=1.7.5 100418 Unable to do partial parsing because saved manifest not found. Starting full parse. 100422 Encountered an error: Parsing Error Invalid sources config given in models\source_hooray_ods.yml @ sources: {'name': 'sp_api', 'description': 'sp_api 原始数据', 'database': 'hooray_ods', 'schema': 'sp_api', 'tables': [{'name': 'listing_sp_ranking', 'description': '', 'freshness': {'warn_after': {'period': 'day', 'count': 1, 'filter': '(year, month, day) >= (year(dateadd(day, -3, current_date())), month(dateadd(day, -3, current_date())), day(dateadd(day, -3, current_date())))'}, 'error_after': {'period': 'day', 'count': 2, 'filter': '(year, month, day) >= (year(dateadd(day, -3, current_date())), month(dateadd(day, -3, current_date())), day(dateadd(day, -3, current_date())))'}} , 'loaded_at_field': 'to_timestamp_ntz(fetch_unixtime)'}]} - at path ['tables'][0]['freshness']: {'warn_after': {'period': 'day', 'count': 1, 'filter': '(year, month, day) >= (year(dateadd(day, -3, current_date())), month(dateadd(day, -3, current_date())), day(dateadd(day, -3, current_date())))'}, 'error_after': {'period': 'day', 'count': 2, 'filter': '(year, month, day) >= (year(dateadd(day, -3, current_date())), month(dateadd(day, -3, current_date())), day(dateadd(day, -3, current_date())))'}} is not valid under any of the given schemas
k
A message from kapa.ai
根据你提供的报错信息,`filter` 字段被放在了
warn_after
和
error_after
里面,这并不是 dbt source freshness 的标准配置方式。 根据 dbt 官方文档和 Elementary 社区的讨论,`filter` 应该直接放在
freshness
下,而不是嵌套在
warn_after
或
error_after
里面。 正确的写法应该如下:
Copy code
yaml sources:   - name: sp_api     description: sp_api 原始数据     database: hooray_ods     schema: sp_api     tables:       - name: listing_sp_ranking         description: ""         freshness:           warn_after: {period: day, count: 1}           error_after: {period: day, count: 2}           filter: "to_date(year || '-' || month || '-' || day) >= dateadd(day, -3, current_date())"         loaded_at_field: "to_timestamp_ntz(year || '-' || month || '-' || day)"
注意事项: -
filter
必须是 SQL 表达式字符串,直接写在
freshness
下。 -
loaded_at_field
也需要拼接成日期或时间戳,确保能被 Snowflake 正确解析。 - 你需要根据实际字段类型调整 SQL 表达式(如 `to_date`、`to_timestamp_ntz` 等)。 如果你遇到 SQL 语法问题,可以先在 Snowflake 控制台测试你的表达式,确保能正确转换 year、month、day 字段为日期或时间戳。 此配置方式参考了 Elementary 社区关于多字段拼接为时间戳的讨论 [相关讨论](https://slack.com/archives/C02CTC89LAX/p1708500107119859)。 如果还有问题,建议贴出具体的 SQL 语法错误,便于进一步排查。