dbt中select *写法在Snowflake平台的性能影响确认
核心结论:Snowflake上dbt CTE使用select *基本不影响性能
一、Snowflake的优化机制能自动处理select *
Snowflake的查询优化器具备**列修剪(Column Pruning)和谓词下推(Predicate Pushdown)**能力,会完整分析整个查询逻辑:
- 无论CTE中写的是
select *还是具体列名,优化器都会识别出最终查询实际用到的列 - 只会从底层模型(stg/int层)或原始表加载这些必要列,不会读取未被使用的冗余列
- 这种优化在查询执行前就完成,不会浪费存储扫描或计算资源
二、dbt社区偏好select *的原因
正如《How we structure our dbt project》指南所述,这种写法是dbt的常见最佳实践,示例代码如下:
with orders as ( select * from {{ ref('stg_jaffle_shop__orders' )}} ), order_payments as ( select * from {{ ref('int_payments_pivoted_to_orders') }} ), orders_and_order_payments_joined as ( select . . . . from orders left join order_payments on orders.order_id = order_payments.order_id ) select * from orders_and_payments_joined
即使下游并未用到源表的所有列,该写法也被广泛使用,核心原因:
- 代码简洁易维护:不用每次底层模型新增列时,都修改CTE的列选择列表
- 模块化解耦:把底层模型的列定义和下游查询的使用逻辑分开,符合dbt面向对象的建模思路,下游只需关注自身需要的列
三、需要显式指定列的场景
虽然select *在大多数场景下安全高效,但以下情况建议明确指定所需列:
- 数据治理要求:比如底层表包含敏感列,需要强制限制下游只能使用非敏感列
- 列转换操作:需要对列做重命名、类型转换、计算时,必须显式指定列并处理
- 极端复杂查询:极少数超复杂的嵌套CTE或多表关联场景,可能导致优化器无法正确识别需要的列(这种情况非常罕见,Snowflake优化器对绝大多数场景都能处理)
总结
在Snowflake上运行dbt时,*CTE中使用select 基本不会影响性能,完全可以遵循社区最佳实践使用该写法提升开发效率。只有在有特定治理需求或需要处理列逻辑时,才需要显式指定所需列。
内容的提问来源于stack exchange,提问作者sparc_spread
相关产品推荐
相关产品推荐

