文章目录
- 一、核心结论
- 二、底层原理解析
-
- [1、视图(View)的本质:SQL 模板](#1、视图(View)的本质:SQL 模板)
- [2、临时表(Temporary Table)的本质:带生命周期的真实表](#2、临时表(Temporary Table)的本质:带生命周期的真实表)
- 三、核心差异对比
- 四、实战案例
-
- 1、视图场景一:封装复杂业务逻辑(报表系统)
- 2、视图场景二:隐藏敏感字段(权限控制)
- 3、临时表场景一:避免重复扫描大表(性能优化)
- [4、临时表场景二:ETL 分步执行(可维护性强)](#4、临时表场景二:ETL 分步执行(可维护性强))
- 五、总结
在数据库开发中,视图(View) 和 临时表(Temporary Table) 是两个很常见又容易被混淆的对象。它们看起来都能"简化查询",但在底层原理、数据特性、性能表现和使用方式上完全不同。
搞清楚两者的区别,可以明显提升 SQL 性能和系统可维护性。
一、核心结论
1、最简明的一句话
视图用于封装查询逻辑(不存数据),临时表用于缓存具体数据(提升性能)。
2、进一步展开说明
-
视图(View)
- 不保存数据,只保存 SQL 逻辑
- 每次查询视图时,都会实时访问底层表
- 更偏向"抽象层 / 接口层"
-
临时表(Temporary Table)
- 实际保存数据,是一次查询或计算后的结果快照
- 在本 Session 或事务中可以反复使用,而不用再访问底表
- 更偏向"中间结果 / 性能优化工具"
3、典型用途对比
- 视图适合:封装复杂 SQL、统一口径报表、隐藏敏感字段、提供稳定数据接口
- 临时表适合:复杂统计分析、批处理、ETL 分步执行、避免多次扫描大表
二、底层原理解析
1、视图(View)的本质:SQL 模板
视图可以理解成一个"起了名字的 SQL 查询模板",数据库只存储它的定义,而不存储查询结果。
基本示例
sql
CREATE VIEW active_users AS
SELECT *
FROM users
WHERE status = 'active';
查询视图时:
sql
SELECT * FROM active_users;
数据库内部会做的事情大致是:
- 把
active_users替换为它的定义 - 将视图 SQL 与你当前的 SQL 合并、重写
- 最终还是去查询
users表
2)视图的特点
- 不存储数据,数据全来自底表
- 每次查询都是实时数据
- 可以简化复杂 SQL 的书写
- 可以屏蔽部分字段,实现权限控制
- 性能不一定更好,复杂视图甚至可能让优化器更难处理
2、临时表(Temporary Table)的本质:带生命周期的真实表
临时表是真真正正的物理表(只不过存在于临时空间),里面存的也是一行一行的真实数据。
1)基本示例
sql
CREATE TEMPORARY TABLE tmp_users AS
SELECT *
FROM users
WHERE status = 'active';
在当前 Session 内,你可以多次查询 tmp_users:
sql
SELECT * FROM tmp_users;
这时数据库读取的是临时表中的数据,而不会再去扫描 users 表。
2)临时表的特点
- 实际存储数据(可以在内存或临时磁盘上)
- 与底表不再实时联动,相当于一个"快照"
- 在当前 Session/事务内可反复使用
- 可以对临时表创建索引、加字段、做各种复杂处理
- Session 结束或显式删除后自动销毁
三、核心差异对比
| 对比项 | 视图(View) | 临时表(Temporary Table) |
|---|---|---|
| 是否存储数据 | 否 | 是 |
| 数据是否实时 | 是(始终从底表读取) | 否(创建时的快照) |
| 是否直接提升性能 | 不保证,甚至可能变慢 | 通常能显著提升性能 |
| 生命周期 | 数据库对象级,通常是长期存在 | Session/事务级,自动销毁 |
| 是否可加索引 | 不能直接加,只能给底表加索引 | 可以单独给临时表加索引 |
| 是否适合多步数据加工 | 不适合,多步处理不容易拆解 | 非常适合,用来存中间结果、分步处理 |
| 典型用途 | 逻辑封装、统一口径、权限控制、抽象层 | 中间结果缓存、复杂计算、批处理、性能优化 |
四、实战案例
1、视图场景一:封装复杂业务逻辑(报表系统)
某零售企业有一个"销售汇总报表",涉及:
- 多表 JOIN:订单表、订单明细表、商品表
- 多种过滤:只统计已支付订单、排除测试订单等
- 多种指标:数量、销售额、毛利等
如果每个使用方都要自己写这套 SQL,不但繁琐,而且容易口径不一致。
1)用视图封装复杂逻辑
sql
CREATE VIEW sales_summary AS
SELECT
p.product_id,
SUM(oi.quantity) AS total_qty,
SUM(oi.quantity * oi.price) AS total_amount
FROM order_item oi
JOIN orders o ON oi.order_id = o.id
JOIN product p ON oi.product_id = p.id
WHERE o.status = 'PAID'
GROUP BY p.product_id;
业务方直接使用视图:
sql
SELECT *
FROM sales_summary
WHERE product_id = 1001;
2)带来的好处
- 所有人都基于同一套统计口径
- 对上层来说,视图就像一张普通表一样简单
- 底层表结构调整时,只需要修改视图定义,上层 SQL 可以不变
2、视图场景二:隐藏敏感字段(权限控制)
员工表中有许多敏感数据:
- salary(工资)
- bank_account(银行卡号)
- id_number(身份证号)
普通业务人员只需要看到基本信息,不该看到隐私数据。
1)通过视图暴露有限字段
sql
CREATE VIEW employee_public AS
SELECT
id,
name,
department
FROM employee;
只给业务账号授权访问 employee_public:
sql
GRANT SELECT ON employee_public TO biz_user;
2)带来的好处
- 不需要对每个 SQL 单独控制字段
- 从根本上隔离了敏感信息的访问
- 视图变成安全的数据接口层
3、临时表场景一:避免重复扫描大表(性能优化)
需求:找出最近三个月消费次数大于 5 且总金额大于 5000 的用户,然后对这一批用户:
- 分析地域分布
- 分析标签情况
- 分析营销触达效果
底表 orders 有千万级记录,如果每次分析都重新扫描 orders,性能会非常差。
1)用临时表抽取目标用户
sql
CREATE TEMPORARY TABLE vip_users AS
SELECT user_id
FROM orders
WHERE order_date >= NOW() - INTERVAL 3 MONTH
GROUP BY user_id
HAVING COUNT(*) > 5
AND SUM(amount) > 5000;
此时 vip_users 一般只有几千或几万行,远小于原始订单表。
2)后续分析基于临时表
sql
-- 地域分布
SELECT vu.user_id, u.region
FROM vip_users vu
JOIN user_info u ON vu.user_id = u.id;
-- 营销触达次数
SELECT vu.user_id, COUNT(*) AS msg_count
FROM vip_users vu
JOIN marketing_msg m ON vu.user_id = m.user_id
GROUP BY vu.user_id;
3)带来的好处
- 大表
orders只扫描一次 - 后续所有分析都针对小表
vip_users,查询非常快 - 中间结果在当前 Session 内可反复使用
4、临时表场景二:ETL 分步执行(可维护性强)
数据团队要把原始订单数据清洗后写入数仓,需要:
- 过滤无效状态
- 过滤金额异常
- 关联商品表补全维度信息
- 最终写入目标表
dw_order
如果写成一条极其复杂的 SQL,维护和调试都很困难。
1)用临时表拆分步骤
sql
-- 第一步:过滤有效订单
CREATE TEMPORARY TABLE step1_clean AS
SELECT *
FROM raw_order
WHERE status IN ('PAID', 'FINISHED');
sql
-- 第二步:过滤金额异常
CREATE TEMPORARY TABLE step2_valid AS
SELECT *
FROM step1_clean
WHERE amount > 0;
sql
-- 第三步:关联商品表,补充品类信息
CREATE TEMPORARY TABLE final_ready AS
SELECT v.*, p.category
FROM step2_valid v
JOIN product p ON v.product_id = p.id;
2)最终写入数仓
sql
INSERT INTO dw_order
SELECT *
FROM final_ready;
3)带来的好处
- 每一步都可以单独检查、回溯
- 出现问题可以只回滚某一步
- SQL 拆分后更易于阅读和维护
五、总结
核心记忆点
- 视图:不存数据,是对查询逻辑的封装与抽象。
- 临时表:存数据,是对中间结果的缓存与复用。
视图更适合:
- 统一统计口径、封装复杂查询
- 对外提供稳定的数据接口
- 控制字段可见性、隐藏敏感数据
临时表更适合:
- 复杂统计分析与中间结果存储
- 避免多次扫描大表、提高查询性能
- ETL、批处理、分步数据加工
视图不存数据,是逻辑层抽象;临时表存数据,是中间结果的物理缓存。视图偏封装和权限控制,临时表偏性能优化和复杂计算。