视图命名需带业务域前缀和类型标识,禁用泛化前缀v_;时间粒度不得嵌入视图名,应通过WHERE或函数参数控制;嵌套不得超过两层;禁止硬编码库名或schema名;优先使用物化表而非复杂视图。

视图名必须带业务域前缀和类型标识
数据库里一堆 v_user、v_order,过三个月连自己都分不清是汇总用的还是权限过滤用的。命名不是为了好看,是为了让别人(包括未来的你)扫一眼就知道它干啥、归谁管、能不能直接查。
实操建议:
- 前缀统一用业务域缩写,比如订单域用 ord_,用户域用 usr_,报表域用 rpt_
- 类型标识紧跟其后:汇总类加 _agg(如 ord_order_monthly_agg),权限过滤类加 _filtered(如 usr_user_active_filtered),ETL中间态加 _stg
- 禁止用 v_ 这种泛化前缀——它没提供任何有效信息,还占一个字符位
- 全小写 + 下划线,避免大小写混用导致跨平台(比如 PostgreSQL 大小写敏感,MySQL 默认不敏感)引发隐性问题
别在视图名里塞时间粒度或日期参数
像 v_sales_2024q3 或 v_user_daily_20241001 这类名字,看着“实时”,其实埋了三个雷:视图不可复用、无法被物化视图/查询重写识别、DDL 变更成本高到没人敢动。
常见错误现象:
- 每月手动建新视图,脚本漏跑一天就断数
- BI 工具缓存了旧视图名,切到新视图要改所有看板
- 临时表迁移时发现几十个带日期的视图,不敢删又不敢留
正确做法:
- 时间维度全部下沉到 WHERE 条件或函数参数里,比如用 WHERE dt BETWEEN ? AND ?
- 如需分区加速,用原生分区表或按 dt 字段建索引,而不是靠视图名“模拟”分区
- 真需要快照语义?用带版本号的表(ord_order_snapshot_v2),而不是视图
避免视图嵌套超过两层
一个视图 SELECT 另一个视图,那个视图又 SELECT 第三个——三层嵌套后,执行计划基本不可读,EXPLAIN 显示的 cost 值会严重失真,而且 MySQL 8.0 以前甚至不支持对嵌套视图下推谓词。
性能与兼容性影响:
- PostgreSQL 12+ 支持较深的视图展开,但嵌套超两层后,pg_get_viewdef() 输出可读性骤降
- SQL Server 对嵌套视图有 32 层限制,但实际到第 5 层就开始报 Maximum nesting level exceeded
- 视图嵌套越深,列血缘追踪越困难,Data Catalog 工具基本失效
怎么控制:
- 所有基础宽表、清洗后事实表、维度表,一律用物化表(CREATE TABLE AS)落地,不走视图
- 视图只做轻量封装:字段别名、简单 JOIN、固定 WHERE(如 status = 'active')
- 如果逻辑实在复杂,拆成「基础视图 + 应用视图」两级,中间层禁止再引用其他视图
视图定义里禁止硬编码库名或 schema 名
SELECT * FROM prod_db.usr_user 这种写法,本地测试用 dev_db 就得全量替换,CI/CD 流水线里一不留神就指向生产库。
容易踩的坑:
- 不同环境 schema 名不同(staging / prod / test),硬编码导致视图创建失败
- 跨库查询在某些引擎(如 Presto、Trino)中 require explicit catalog.schema.table,但硬编码会让迁移变脆弱
- SHOW CREATE VIEW 导出的 DDL 无法直接复用
解决方案:
- 所有视图在目标 schema 内创建,并用 SET search_path 或连接时指定默认 schema
- 必须跨 schema 查询时,用变量或部署时模板替换(如 {{ target_schema }}.usr_user),而不是写死
- 定期用 SELECT viewname, definition FROM pg_views(PostgreSQL)或 INFORMATION_SCHEMA.VIEWS 扫描含 . 的视图定义,自动告警
真正难的不是起名规则,而是每次建视图前,花三十秒想清楚:这个逻辑,是不是真的该放在视图里?还是该压进 ETL 任务、或者干脆用 CTE 临时写?










