底层表更改时更新物化视图
Posted
技术标签:
【中文标题】底层表更改时更新物化视图【英文标题】:Update materialized view when urderlying tables change 【发布时间】:2011-01-02 22:10:24 【问题描述】:我有一个这样定义的物化视图:
CREATE MATERIALIZED VIEW M_FOO
REFRESH COMPLETE ON COMMIT
AS
SELECT FOO_ID, BAR
FROM FOO
WHERE BAR IS NOT NULL
GROUP BY FOO_ID, BAR
/
COMMENT ON MATERIALIZED VIEW M_FOO IS 'Foo-Bar pairs';
我写的是一种缓存:源表很大,但不同对的数量相当少。我需要这些对让它们与其他表连接。到目前为止一切顺利:它绝对可以加快查询速度。
但我想确保视图不包含过时的数据。基础表每月修改四到五次,但我不一定知道什么时候。我知道可以定义物化视图,以便在源表更改时更新。但是,文档变得相当复杂。
我需要的确切语法是什么 用吗?
我是否需要创建一个物化 查看日志?
快和快有什么区别 并完成刷新?
【问题讨论】:
【参考方案1】:以相反的顺序回答您的问题
快速刷新也称为增量刷新。这应该会给你一个关于差异的线索。 COMPLETE 刷新从头开始重建整个 MVIEW,而 FAST 刷新仅应用 DML 对馈送表执行的更改。
为了执行 FAST 刷新,您需要适当的 MVIEW LOG。这会跟踪基础表数据的变化,从而使 Oracle 能够有效地将 delta 应用于物化视图,而不是查询整个表。
至于语法,这里是基础:
SQL> create materialized view log on emp
2 with rowid, primary key, sequence (deptno, job)
3 including new values
4 /
Materialized view log created.
SQL> create materialized view emp_mv
2 refresh fast on commit
3 as
4 select deptno, job from emp
5 group by deptno, job
6 /
Materialized view created.
SQL>
ON COMMIT
子句意味着 MVIEW 以事务方式刷新(与 ON DEMAND
相对,后者是批量定期刷新)。 REFRESH
子句指定是应用增量刷新还是完全刷新。有一些类别的查询会强制使用COMPLETE
刷新,尽管这些似乎随着每个新版本的 Oracle 而减少。
快速测试看看它是否有效......
SQL> select * from emp_mv
2 order by deptno, job
3 /
DEPTNO JOB
---------- ---------
10 MANAGER
10 PRESIDENT
10 SALES
20 ANALYST
20 CLERK
20 MANAGER
30 CLERK
30 MANAGER
30 SALESMAN
40 CLERK
40 DOGSBODY
11 rows selected.
SQL>
来个新纪录怎么样?
SQL> insert into emp (empno, ename, deptno, job)
2 values (6666, 'GADGET', 40, 'INSPECTOR')
3 /
1 row created.
SQL> commit
2 /
Commit complete.
SQL> select * from emp_mv
2 order by deptno, job
3 /
DEPTNO JOB
---------- ---------
10 MANAGER
10 PRESIDENT
10 SALES
20 ANALYST
20 CLERK
20 MANAGER
30 CLERK
30 MANAGER
30 SALESMAN
40 CLERK
40 DOGSBODY
40 INSPECTOR
12 rows selected.
SQL>
您可以在the SQL Reference 中找到有关语法的更多详细信息。 Materialized View chapter in the Data Warehousing Guide也值得一读。
尽管下面的评论者担心,这确实像宣传的那样有效。不幸的是,发布演示的常用位置(SQL Fiddle、dbfiddle)不允许物化视图。我在 Oracle SQL Live 上发布了一些内容(需要免费的 Oracle 帐户):我正在等待 Oracle 批准它,并会在它到达时更新这个问题。
【讨论】:
谢谢,我想我终于明白了。 ON COMMIT 部分启用更新,REFRESH 部分微调方法。我只需要一个物化视图日志即可快速刷新。 怎么统计结果11,但是select返回12行?这是不稳定的。【参考方案2】:快速刷新只会将更改的数据插入/更新/删除到实体化视图中。完全刷新将清空物化视图,然后复制所有行。
“提交时”意味着每当在主表中提交更改时,都会刷新物化视图。因此,您当前的语法将非常低效。每次有人更改 foo 中的任何行时,m_foo 都会被截断,然后 foo 表中的每一行都会被插入。
你可以通过快速刷新做得更好,只有 foo 中的修改行将被发送到 m_foo。这使您无需太多开销即可保持一致性。
使用主键在 foo 上创建物化视图日志; -- 假设你有一个主键,你应该 创建物化视图 m_foo 在提交时快速刷新为 \;
如果您使用 db 链接,或者拥有 foo 的架构不是拥有 m_foo 的架构,那么授权和同义词还有一些额外的微妙之处。
【讨论】:
你的答案也很好,但我只能选择一个。谢谢。 如果源是视图,是否支持快速刷新?以上是关于底层表更改时更新物化视图的主要内容,如果未能解决你的问题,请参考以下文章
Postgres:更新与物化视图连接的表?错误:视图无法在物化视图中锁定行