Oracle物化视图 #

一、物化视图概述 #

1.1 什么是物化视图 #

物化视图(Materialized View)是存储查询结果的数据库对象,与普通视图不同,物化视图实际存储数据,可以定期刷新。

text
物化视图 vs 普通视图
├── 普通视图
│   ├── 只存储查询定义
│   ├── 每次查询时执行
│   └── 不占用存储空间
└── 物化视图
    ├── 存储实际数据
    ├── 可定期刷新
    └── 占用存储空间

1.2 应用场景 #

text
物化视图应用场景
├── 数据仓库
│   └── 预计算聚合数据
├── 分布式数据库
│   └── 数据复制
├── 移动计算
│   └── 数据同步
└── 性能优化
    └── 加速复杂查询

二、创建物化视图 #

2.1 基本语法 #

sql
-- 创建物化视图基本语法
CREATE MATERIALIZED VIEW mv_name
    [BUILD IMMEDIATE|DEFERRED]
    [REFRESH [FAST|COMPLETE|FORCE] [ON DEMAND|ON COMMIT]]
    [ENABLE|DISABLE QUERY REWRITE]
AS
SELECT statement;

2.2 创建简单物化视图 #

sql
-- 创建物化视图
CREATE MATERIALIZED VIEW mv_emp_salary
BUILD IMMEDIATE
REFRESH COMPLETE ON DEMAND
AS
SELECT 
    department_id,
    COUNT(*) AS employee_count,
    AVG(salary) AS avg_salary,
    SUM(salary) AS total_salary
FROM employees
GROUP BY department_id;

-- 查询物化视图
SELECT * FROM mv_emp_salary;

2.3 创建带刷新策略的物化视图 #

sql
-- 完全刷新
CREATE MATERIALIZED VIEW mv_dept_stats
REFRESH COMPLETE ON DEMAND
AS
SELECT department_id, COUNT(*) AS cnt
FROM employees
GROUP BY department_id;

-- 快速刷新(需要物化视图日志)
CREATE MATERIALIZED VIEW LOG ON employees
WITH ROWID, SEQUENCE (department_id, salary)
INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW mv_emp_fast
REFRESH FAST ON COMMIT
AS
SELECT department_id, SUM(salary) AS total_sal
FROM employees
GROUP BY department_id;

-- 定时刷新
CREATE MATERIALIZED VIEW mv_daily_stats
REFRESH COMPLETE
START WITH SYSDATE
NEXT SYSDATE + 1
AS
SELECT * FROM sales WHERE sale_date >= TRUNC(SYSDATE) - 30;

三、刷新策略 #

3.1 刷新方式 #

sql
-- COMPLETE:完全刷新,重新执行查询
-- FAST:增量刷新,只刷新变化的数据
-- FORCE:自动选择刷新方式
-- NEVER:从不刷新

-- 手动刷新
EXEC DBMS_MVIEW.REFRESH('mv_emp_salary', 'C');  -- 完全刷新
EXEC DBMS_MVIEW.REFRESH('mv_emp_salary', 'F');  -- 快速刷新

-- 刷新所有物化视图
EXEC DBMS_MVIEW.REFRESH_ALL_MVIEWS;

3.2 刷新时机 #

sql
-- ON DEMAND:按需刷新(默认)
CREATE MATERIALIZED VIEW mv_on_demand
REFRESH ON DEMAND
AS SELECT * FROM employees;

-- ON COMMIT:提交时刷新
CREATE MATERIALIZED VIEW mv_on_commit
REFRESH FAST ON COMMIT
AS SELECT department_id, COUNT(*) AS cnt
FROM employees GROUP BY department_id;

-- 定时刷新
CREATE MATERIALIZED VIEW mv_scheduled
REFRESH COMPLETE
START WITH SYSDATE
NEXT SYSDATE + 1/24  -- 每小时刷新
AS SELECT * FROM employees;

四、查询重写 #

4.1 启用查询重写 #

sql
-- 创建支持查询重写的物化视图
CREATE MATERIALIZED VIEW mv_emp_dept
REFRESH COMPLETE ON DEMAND
ENABLE QUERY REWRITE
AS
SELECT 
    d.department_name,
    COUNT(*) AS employee_count,
    AVG(e.salary) AS avg_salary
FROM employees e
JOIN departments d ON e.department_id = d.department_id
GROUP BY d.department_name;

-- 查询重写示例
-- 原始查询
SELECT d.department_name, AVG(e.salary)
FROM employees e
JOIN departments d ON e.department_id = d.department_id
GROUP BY d.department_name;

-- Oracle自动使用物化视图

4.2 查看查询重写 #

sql
-- 查看执行计划
EXPLAIN PLAN FOR
SELECT d.department_name, AVG(e.salary)
FROM employees e
JOIN departments d ON e.department_id = d.department_id
GROUP BY d.department_name;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

五、物化视图管理 #

5.1 查看物化视图 #

sql
-- 查看物化视图信息
SELECT mview_name, refresh_method, refresh_mode, last_refresh_date
FROM user_mviews;

-- 查看物化视图详细信息
SELECT * FROM user_mviews WHERE mview_name = 'MV_EMP_SALARY';

-- 查看物化视图日志
SELECT master, log_table FROM user_mview_logs;

5.2 修改物化视图 #

sql
-- 修改刷新策略
ALTER MATERIALIZED VIEW mv_emp_salary
REFRESH COMPLETE ON DEMAND;

-- 启用查询重写
ALTER MATERIALIZED VIEW mv_emp_salary
ENABLE QUERY REWRITE;

-- 禁用查询重写
ALTER MATERIALIZED VIEW mv_emp_salary
DISABLE QUERY REWRITE;

5.3 删除物化视图 #

sql
-- 删除物化视图
DROP MATERIALIZED VIEW mv_emp_salary;

-- 保留物化视图表
DROP MATERIALIZED VIEW mv_emp_salary PRESERVE TABLE;

六、总结 #

物化视图要点:

刷新方式 说明 适用场景
COMPLETE 完全刷新 数据量小
FAST 增量刷新 数据量大
FORCE 自动选择 通用

最佳实践:

  1. 选择合适的刷新策略
  2. 启用查询重写优化性能
  3. 定期监控刷新状态
  4. 合理设置刷新频率
  5. 注意存储空间占用

下一步,让我们学习分区表!

最后更新:2026-03-27