视图不是中间数据缓冲层,它根本不缓存数据;其在ETL中实际承担“标准化出口”角色,仅固化清洗逻辑——统一字段名、处理空值、转换类型、对齐多源命名,必须显式定义字段、禁用SELECT*、避免WHERE过滤业务状态,性能瓶颈时应改用物化表或CTE。

视图不是中间数据缓冲层,它根本不缓存数据——这是最常被误解的起点。如果你在 ETL 流程里把它当“缓冲层”用,大概率会遇到调度变慢、字段莫名消失、下游解析报错这些事。
视图在ETL中实际承担的角色是“标准化出口”
它不存数据,只固化清洗逻辑:统一字段名、处理空值、转换类型、对齐多源命名。比如原始订单表里有 order_date_str(字符串)、ordertime(timestamp)、created_at(带时区),视图里必须显式写成:CAST(order_date_str AS DATE) AS order_date,而不是依赖上游自动推断。
- 必须显式列出所有字段,禁用
SELECT *——否则上游加个is_test字段,下游pandas.read_sql就可能因列数/顺序突变而报ValueError: DataFrame columns mismatch - 涉及多源表
JOIN时,用LEFT JOIN+COALESCE(u.name, o.customer_name)做兜底,别假设外键一定存在 - 别在视图里写
WHERE status = 'paid'这类业务过滤——这会让 Airflow 每次调用都重跑全量逻辑,且无法复用给对账、退款等其他场景
PostgreSQL 和 MySQL 视图执行行为差异直接影响ETL稳定性
PostgreSQL 每次调用都会把视图定义内联重写进查询树;MySQL 8.0+ 大部分情况也如此,但一旦视图含子查询或窗口函数,优化器可能悄悄生成临时表(EXPLAIN 里看到 Derived 或 Materialize),ETL 调度任务就从秒级变成分钟级。
- 在 PostgreSQL 中,含
LATERAL或递归 CTE 的视图,会让调度器反复解析语法树——建议拆成物化视图或CREATE TEMP TABLE AS ... - MySQL 中,视图嵌套超过 3 层(A → B → C → D)容易触发优化器退化,用
SHOW CREATE VIEW view_d查看实际展开后的 SQL 长度和嵌套深度 - 两个库都不支持视图里用会话变量(如
@last_run_time),ETL 参数必须由调度器(Airflow/Azkaban)注入,不能指望视图“记住”上次时间
字段命名冲突会让下游工具直接崩溃
当多个源表都有 id、name、updated_at,又没在视图里重命名,dbt 或 Spark SQL 解析时就会卡在 ProgrammingError: column reference "id" is ambiguous。
- 强制要求别名:用
o.id AS order_id、u.id AS user_id,而不是o.id简写 - 避免用下划线开头的字段名(如
_deleted),某些 JDBC 驱动会忽略或截断 - 日期字段统一用
DATE或TIMESTAMP WITHOUT TIME ZONE,别混用TIMESTAMP WITH TIME ZONE,否则 Spark 写 Parquet 时可能报Cannot cast timestamp with time zone to timestamp without time zone
真正需要缓冲的环节(比如大表关联后结果复用、中间聚合快照),该用临时表或物化视图,而不是硬扛 SELECT * FROM sales_view —— 后者每次都是重新算,不是“缓冲”,是“重复劳动”。

















