如何捕获DBT运行模型的内存利用率及排查高内存消耗问题
捕获dbt运行时内存利用率的方法
- 内置工具捕获:dbt 1.4及以上版本可以直接在运行命令后加
--profile-memory标志,运行结束后会输出每个执行步骤的峰值内存占用统计;更低版本可以加--log-level debug参数运行,debug日志中会包含各阶段的内存快照记录。 - 系统工具捕获:macOS/Linux环境可直接使用
time -v dbt run [其他参数]命令运行,输出结果中的Maximum resident set size字段即为运行过程中的最大内存占用;Windows环境可以在PowerShell中运行while ($true) { Get-Process -Name dbt -ErrorAction SilentlyContinue | Select-Object Timestamp,WorkingSet | Export-Csv -Path dbt_mem.csv -Append; Start-Sleep 1 },每秒采样一次dbt进程的内存占用并存储到csv文件。 - 自定义脚本捕获:如果需要更细粒度的阶段内存统计,可以编写Python包装脚本,通过psutil库启动dbt子进程并定时采样内存,匹配dbt运行日志的阶段标识,即可得到每个模型运行对应的内存占用。
高内存消耗排查方案
环境差异排查
- 首先对齐两边的依赖版本:分别在GCP环境和本地运行
dbt --version,核对dbt-core、dbt-bigquery以及其他Python依赖的版本号,本地环境通常会安装更多额外的dbt插件、数据分析依赖包,冗余依赖会显著提升dbt启动和运行时的基础内存占用,而GCP的k8s运行镜像一般仅安装运行必要的精简依赖。 - 对齐dbt运行配置:核对两边
profiles.yml和dbt_project.yml中的配置项:- 检查
threads参数,本地如果配置的并行线程数远高于GCP环境,多线程并行运行模型会线性提升内存占用 - 检查是否开启了额外的本地输出,比如本地开启了
write_html、write_json生成运行报告,会额外加载全量元数据到内存 - 检查GBQ连接配置,本地如果开启了表缓存、全量元数据拉取等预览配置,会把关联表的元数据甚至样本数据拉到本地,而GCP近源运行仅拉取计算必要的数据。
- 检查
运行逻辑排查
- 清理本地残留文件后重试:运行前先执行
dbt clean清理target目录下的历史编译文件、日志缓存,再运行任务,排除历史残留的大量元数据被加载到内存的问题。 - 逐模型排查内存占用:使用
dbt run --select 单个模型名命令逐个运行5个模型,定位是否有单个模型存在异常高内存占用,重点检查模型中是否使用了run_query()、load_result()这类会把查询结果全量加载到内存的宏,或者是否使用了Python模型把全量表数据拉到本地计算,哪怕最终输出只有500条,中间过程也会占用大量内存。 - 核对项目规模:如果本地的dbt项目目录下除了这5个运行的模型,还有其他大量未运行的模型、测试、快照等资源,dbt启动时会加载全量项目的依赖关系图和元数据,哪怕仅运行5个模型也会占用额外内存,而GCP如果是仅部署了这5个模型的精简项目,基础内存占用就会低很多。
验证测试
控制变量做对齐测试:两边使用相同的dbt版本、相同的threads参数、相同的配置项,运行前都执行dbt clean清理缓存,再运行相同的任务,如果内存差异仍然存在,可以通过内存采样的结果定位是启动阶段内存高还是模型运行阶段内存高,进一步定位问题。
内容的提问来源于stack exchange,提问作者chandra
相关产品推荐
相关产品推荐

