oracle物化视图

发布于:2025-06-27 ⋅ 阅读:(23) ⋅ 点赞:(0)

物化视图的定义

物化视图是一种预先计算并存储查询结果的数据库对象。与普通视图不同,普通视图只是一个 SQL 查询的定义,每次查询时都需要动态执行 SQL 语句;而物化视图会实际存储查询结果,就像一个物理表一样。物化视图的数据会定期或在特定条件下刷新,以保证与基表数据的一致性。

物化视图的用途

物化视图在数据库中有多种重要用途,具体如下:

  • 提高查询性能:对于复杂的查询,尤其是涉及多表连接、聚合函数的查询,使用物化视图可以显著提高查询速度,因为查询结果已经预先计算并存储好了。
  • 减少资源消耗:由于物化视图减少了对基表的频繁查询,从而降低了数据库的 CPU、I/O 等资源消耗。
  • 实现数据汇总:可以使用物化视图来预先计算和存储数据的汇总信息,如统计报表、聚合数据等。
  • 支持数据仓库和 OLAP:在数据仓库环境中,物化视图经常被用于存储历史数据和聚合数据,以支持联机分析处理(OLAP)。
  • 提供数据快照:物化视图可以提供某个时间点的数据快照,适用于需要历史数据对比的场景。

物化视图的创建

创建物化视图的基本语法如下:

CREATE MATERIALIZED VIEW mv_name
[BUILD IMMEDIATE | BUILD DEFERRED]
[REFRESH [FAST | COMPLETE | FORCE]
  [ON DEMAND | ON COMMIT]
  [START WITH date] 
  [NEXT date]
  [WITH PRIMARY KEY | WITH ROWID]
  [USING INDEX | USING NO INDEX]
  [ENABLE | DISABLE QUERY REWRITE]
AS subquery;

下面对语法中的关键参数进行说明:

  • BUILD IMMEDIATE | BUILD DEFERRED:指定创建物化视图时是否立即填充数据。BUILD IMMEDIATE 表示创建时立即填充数据(默认值);BUILD DEFERRED 表示创建时不填充数据,需要手动刷新后才有数据。
  • REFRESH:指定物化视图的刷新方式和时间:
    • FAST:只刷新自上次刷新以来发生变化的数据,需要基表上有物化视图日志支持。
    • COMPLETE:完全重新生成整个物化视图。
    • FORCE:优先使用 FAST 刷新,如果不可行则使用 COMPLETE 刷新(默认值)。
    • ON DEMAND:手动刷新,需要执行 DBMS_MVIEW.REFRESH 过程(默认值)。
    • ON COMMIT:在基表发生提交时自动刷新,要求物化视图必须基于单个表,且刷新方式必须为 FAST。
  • WITH PRIMARY KEY | WITH ROWID:指定刷新时使用的标识符。WITH PRIMARY KEY 使用主键(默认值);WITH ROWID 使用 ROWID,适用于没有主键的表,刷新性能更高。
  • ENABLE | DISABLE QUERY REWRITE:启用或禁用查询重写。启用后,Oracle 会自动将符合条件的查询重定向到物化视图上执行,以提高查询性能。

下面是创建物化视图的示例:

-- 创建一个简单的物化视图,每天晚上10点刷新
CREATE MATERIALIZED VIEW emp_salary_mv
BUILD IMMEDIATE
REFRESH COMPLETE
START WITH TO_DATE('2025-06-25 22:00:00', 'YYYY-MM-DD HH24:MI:SS')
NEXT SYSDATE + 1
AS
SELECT department_id, AVG(salary) AS avg_salary, COUNT(*) AS emp_count
FROM employees
GROUP BY department_id;

-- 创建一个快速刷新的物化视图,在基表提交时自动刷新
CREATE MATERIALIZED VIEW log ON employees
WITH PRIMARY KEY;

CREATE MATERIALIZED VIEW dept_emp_mv
BUILD IMMEDIATE
REFRESH FAST
ON COMMIT
WITH PRIMARY KEY
AS
SELECT d.department_id, d.department_name, COUNT(e.employee_id) AS emp_count
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id
GROUP BY d.department_id, d.department_name;

物化视图的刷新

刷新物化视图有多种方式,具体如下:

  • 自动刷新:通过 ON COMMIT 或定期调度(如 START WITH 和 NEXT 参数)实现自动刷新。
  • 手动刷新:使用 DBMS_MVIEW.REFRESH 过程手动刷新物化视图,示例如下:
-- 手动刷新单个物化视图
EXEC DBMS_MVIEW.REFRESH('emp_salary_mv');

-- 手动刷新多个物化视图
EXEC DBMS_MVIEW.REFRESH('emp_salary_mv, dept_emp_mv');

-- 快速刷新物化视图
EXEC DBMS_MVIEW.REFRESH('dept_emp_mv', 'F');

-- 完全刷新物化视图
EXEC DBMS_MVIEW.REFRESH('emp_salary_mv', 'C');

物化视图的查询

查询物化视图的方式与查询普通表相同,例如:

SELECT * FROM emp_salary_mv;
SELECT department_name, emp_count FROM dept_emp_mv;

物化视图的管理

  • 查看物化视图信息:可以通过查询数据字典视图来获取物化视图的信息,例如:
-- 查看所有物化视图
SELECT * FROM USER_MVIEWS;

-- 查看物化视图的刷新状态
SELECT * FROM USER_MVIEW_REFRESH_TIMES;

  • 修改物化视图:使用 ALTER MATERIALIZED VIEW 语句修改物化视图的属性,例如:
-- 修改物化视图的刷新方式
ALTER MATERIALIZED VIEW emp_salary_mv
REFRESH COMPLETE
START WITH SYSDATE + 1/24
NEXT SYSDATE + 1;

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

  • 删除物化视图:使用 DROP MATERIALIZED VIEW 语句删除物化视图,例如:
DROP MATERIALIZED VIEW emp_salary_mv;

物化视图的注意事项

在使用物化视图时,有一些注意事项需要了解:

  • 刷新开销:物化视图的刷新会带来一定的开销,尤其是 COMPLETE 刷新,可能会影响数据库性能。因此,需要合理安排刷新频率。
  • 数据一致性:物化视图的数据是定期刷新的,因此在两次刷新之间,物化视图的数据可能与基表数据不一致。如果需要实时数据,应使用普通视图。
  • 查询重写:启用查询重写后,Oracle 优化器会自动选择使用物化视图,但需要满足一定的条件,如查询语句与物化视图的定义完全匹配。
  • 空间占用:物化视图会占用额外的磁盘空间,因为它存储了实际的数据。
  • 依赖关系:物化视图依赖于基表,如果基表结构发生变化,可能需要重建物化视图。

通过合理使用物化视图,可以显著提高复杂查询的性能,降低数据库负载,适用于数据仓库、报表系统等对查询性能要求较高的场景。