dbt运行模型报列不存在但SQL客户端运行正常问题排查
故障原因
- dbt v0.20.0及以上版本针对Redshift适配器新增了表列元数据预校验逻辑,该逻辑会在执行你编写的模型SQL之前,先查询目标表的现有列信息,和模型预期输出的列做对齐校验,这个校验步骤的SQL不会输出到target目录的编译文件中,所以你单独跑编译后的SQL不会报错。
- dbt v0.21.0版本的Redshift适配器存在已知元数据解析bug:如果目标表历史上有过列重命名、或者模型SQL中的CTE别名和历史列名重名,元数据解析逻辑会错误将历史别名/CTE别名识别为模型需要输出的列,去现有表中匹配,匹配不到就抛出列不存在的错误,即使是全量刷新、改为table物化也会触发该校验,因为该校验在全量重建表之前就会执行。
- 若你的dbt项目中配置了
persist_docs或者列级约束,v0.21版本的列约束校验逻辑也可能拉取错误的历史列元数据做匹配,触发该报错。
解决方案
临时修复(快速恢复生产作业)
在dbt_project.yml或者该模型的config块中添加如下配置,关闭列预校验逻辑:
# 针对单个模型配置 {{ config( materialized = 'incremental', +on_schema_change = 'ignore', meta = { "dbt": { "skip_columns_check": true } } ) }} # 全局配置(针对所有Redshift模型) models: +on_schema_change: 'ignore' vars: disable_column_check: true
配置完成后先执行一次全量刷新:dbt run -s my_model --full-refresh,即可恢复作业运行。
永久修复
- 升级Redshift适配器到兼容版本:dbt-redshift 0.21.1及以上版本已经修复了该元数据解析bug,你可以在
requirements.txt中升级适配器版本:
升级后执行dbt-redshift>=0.21.1dbt deps重新安装依赖,再删除target目录重新运行即可。 - 如果不方便升级版本,可以手动清理缓存+重建表:
- 执行
dbt clean清理本地缓存 - 在Redshift中手动删除目标表:
DROP TABLE IF EXISTS my_schema.my_model CASCADE; - 执行
dbt run -s my_model --full-refresh重新构建全量表
- 执行
- 额外检查:确认模型SQL中没有使用和历史列名重名的CTE别名,避免再次触发元数据解析bug。
内容的提问来源于stack exchange,提问作者Joseph H
相关产品推荐
相关产品推荐

