materialized view(1)

本文探讨了Oracle中物化视图无法快速刷新的两个特殊原因:一是通过同义词引用基表,二是从涉及多表连接且含有复杂表达式的查询创建物化视图。
  1. 这两天偶然发现两个导致物化视图无法快速刷新的原因刷新,这两个原因在Oracle的文档上并没有明确给出,在MV_CAPABILITIES_TABLE中给出的msgno在文档中也找不到对应的说明。
  2. 下面做两个简单的例子重新这两个错误:
  3. SQL> CREATE TABLE TEST AS SELECT MOD(ROWNUM, 5) COL1, ROWNUM COL2 FROM ALL_OBJECTS;
  4. 表已创建。
  5. SQL> CREATE MATERIALIZED VIEW LOG ON TEST WITH ROWID, SEQUENCE (COL1, COL2) INCLUDING NEW VALUES;
  6. 实体化视图日志已创建。
  7. SQL> CREATE MATERIALIZED VIEW MV_TEST REFRESH FAST AS SELECT COL1, SUM(COL2), COUNT(COL2), COUNT(*)
  8. 2 FROM TEST GROUP BY COL1;
  9. 实体化视图已创建。
  10. 上面建立的这个简单的物化视图显然是可以快速刷新的,下面做点变化,建立一个指向基表的同义词,然后建立物化视图的时候指向同义词。
  11. SQL> CREATE SYNONYM C_TEST FOR TEST;
  12. 同义词已创建。
  13. SQL> DROP MATERIALIZED VIEW MV_TEST;
  14. 实体化视图已删除。
  15. SQL> CREATE MATERIALIZED VIEW MV_TEST REFRESH FAST AS SELECT COL1, SUM(COL2), COUNT(COL2), COUNT(*)
  16. 2 FROM C_TEST GROUP BY COL1;
  17. FROM C_TEST GROUP BY COL1
  18. *
  19. ERROR 位于第 2 行:
  20. ORA-12015: cannot create a fast refresh materialized view from a complex query
  21. 现在出现错误了,检查一下错误原因:
  22. SQL> BEGIN
  23. 2 DBMS_MVIEW.EXPLAIN_MVIEW('SELECT COL1, SUM(COL2), COUNT(COL2), COUNT(*)
  24. 3 FROM C_TEST GROUP BY COL1');
  25. 4 END;
  26. 5 /
  27. PL/SQL 过程已成功完成。
  28. SQL> COL MSGTXT FORMAT A80
  29. SQL> SELECT MSGNO, MSGTXT FROM MV_CAPABILITIES_TABLE 
  30. 2 WHERE CAPABILITY_NAME = 'REFRESH_FAST_AFTER_INSERT';
  31. MSGNO MSGTXT
  32. ---------- ---------------------------------------------------------------
  33. 2101 mv references a synonym in the FROM list
  34. 很显然是由于引用了同义词造成的,但是这个错误很奇怪,首先Oracle的文档里并没有明确说明不能引用同义词(也可能是我没有看到),而且Oracle的文档中也没有看到2101的错误。
  35. 对这个错误的解决方法就是不要使用同义词,直接使用基表,当然如果非要利用同义词来达到隐藏基表的目的,可以考虑使用视图代替,入下例,当然,视图和同义词还是有很多差别的,这里就不再讨论了。
  36. SQL> CREATE VIEW V_TEST AS SELECT * FROM TEST;
  37. 视图已建立。
  38. SQL> CREATE MATERIALIZED VIEW MV_TEST REFRESH FAST AS SELECT COL1, SUM(COL2), COUNT(COL2), COUNT(*)
  39. 2 FROM V_TEST GROUP BY COL1;
  40. 实体化视图已创建。
  41. 下面看第二个问题:
  42. SQL> CREATE TABLE TEST1 AS SELECT * FROM TEST;
  43. 表已创建。
  44. SQL> CREATE MATERIALIZED VIEW LOG ON TEST1 WITH ROWID, SEQUENCE (COL1, COL2) INCLUDING NEW VALUES;
  45. 实体化视图日志已创建。
  46. SQL> CREATE MATERIALIZED VIEW MV_TEST_TEST1 REFRESH FAST AS
  47. 2 SELECT A.ROWID A_ROWID, B.ROWID B_ROWID, A.COL1, A.COL2||B.COL2 COL2 
  48. 3 FROM TEST A, TEST1 B
  49. 4 WHERE A.COL2 = B.COL2;
  50. FROM TEST A, TEST1 B
  51. *
  52. ERROR 位于第 3 行:
  53. ORA-12015: cannot create a fast refresh materialized view from a complex query
  54. SQL> TRUNCATE TABLE MV_CAPABILITIES_TABLE;
  55. 表已截掉。
  56. SQL> BEGIN
  57. 2 DBMS_MVIEW.EXPLAIN_MVIEW('SELECT A.COL1, A.COL2||B.COL2 COL2 FROM TEST A, TEST1 B
  58. 3 WHERE A.COL2 = B.COL2');
  59. 4 END;
  60. 5 /
  61. PL/SQL 过程已成功完成。
  62. SQL> SELECT MSGNO, MSGTXT FROM MV_CAPABILITIES_TABLE 
  63. 2 WHERE CAPABILITY_NAME = 'REFRESH_FAST_AFTER_INSERT';
  64. MSGNO MSGTXT
  65. ---------- ---------------------------------------------------------------
  66. 2113 expression in select list references multiple tables or views
  67. 2061 one or more joins present in mv
  68. 这个解释描述的也比较清楚,一个表达式同时参考了多个表。对于同一个中的字段是可以进行‘||’操作的。
  69. SQL> CREATE MATERIALIZED VIEW MV_TEST_TEST1 REFRESH FAST AS
  70. 2 SELECT A.ROWID A_ROWID, B.ROWID B_ROWID, A.COL1, 
  71. 3 A.COL2||A.COL1 COL2, B.COL1||B.COL2 COL3
  72. 4 FROM TEST A, TEST1 B
  73. 5 WHERE A.COL2 = B.COL2;
  74. 实体化视图已创建。
  75. 但是,同样Oracle在文档中并没有说明这一点,上面的两个MSGNO号码在文档中也是找不到对应关系的。怀疑Oracle的msgno是连续的或者基本上是连续的,也就是说,还有很多类似的原因会导致Oracle的物化视图无法刷新,只是不清楚Oracle为什么没有写在文档中。
<think> 我们正在讨论CREATE MATERIALIZED VIEW(创建物化视图)的相关信息。根据引用内容,我们可以总结如下: 1. 语法(参考引用[2][3][4]): - 基本语法:`CREATE MATERIALIZED VIEW [view_name] ... AS SELECT ...` - 可以指定并行选项(PARALLEL)、构建方式(BUILD IMMEDIATE)、刷新方式(REFRESH FORCE)以及自动刷新的时间(如`START WITH ... NEXT ...`) - 可以指定存储参数(WITH (storage_parameter))和表空间(TABLESPACE) - 可以选择创建时是否包含数据(WITH [NO] DATA) 2. 使用方法: - 创建后,物化视图会存储查询结果,类似于一张表。 - 需要刷新(REFRESH)来更新数据,刷新可以是全量或增量(引用[1]提到REFRESH INCREMENTAL)。 - 刷新方式:全量刷新(COMPLETE)或快速刷新(FAST,即增量刷新,但需要满足一定条件)。 - 自动刷新:可以使用`START WITH ... NEXT ...`子句设置自动刷新的时间间隔(引用[3]示例)。 3. 应用场景: - 数据仓库:用于预计算和存储聚合数据,加速复杂查询。 - 远程数据复制:在分布式环境中,物化视图可以缓存远程数据库的数据。 - 提高查询性能:当查询涉及大量数据的聚合或连接时,物化视图可以避免每次执行都进行全量计算。 4. 注意事项(参考引用[2][4]): - 创建时会对基表加独占锁,如果无法锁定则失败。 - 不支持在临时表上创建全量物化视图。 - 创建后,基表的DDL操作可能受限。 - 物化视图本身不支持IUD操作(插入、更新、删除),只能通过刷新来更新数据。 5. 示例(参考引用[3]): ```sql CREATE MATERIALIZED VIEW mv_emp PARALLEL BUILD IMMEDIATE REFRESH FORCE START WITH sysdate NEXT sysdate+(1/(24*60)) WITH PRIMARY KEY AS SELECT count(*) FROM emp; ``` 这个示例创建了一个物化视图mv_emp,它立即构建(BUILD IMMEDIATE),强制刷新(REFRESH FORCE),并且设置每分钟自动刷新一次。 根据以上信息,我们可以组织回答。 </think>### CREATE MATERIALIZED VIEW 详解 #### 📜 基本语法 ```sql CREATE MATERIALIZED VIEW mv_name [ (column1, column2, ...) ] -- 可选列名 [ WITH ( storage_parameter = value ) ] -- 存储参数 [ TABLESPACE tablespace_name ] -- 表空间 [ BUILD { IMMEDIATE | DEFERRED } ] -- 构建时机 [ REFRESH [ FAST | COMPLETE | FORCE ] ] -- 刷新模式 [ ON [ DEMAND | COMMIT ] ] -- 刷新触发方式 [ START WITH start_time NEXT next_interval ] -- 自动刷新计划 AS SELECT ... -- 基础查询 [ WITH [ NO ] DATA ]; -- 是否初始加载数据 ``` #### 🔧 核心参数说明 1. **REFRESH 模式** - `FAST`:增量刷新(需满足物化视图日志条件)[^2] - `COMPLETE`:全量重建 - `FORCE`:优先尝试增量,失败则全量(**推荐**)[^3] ```sql REFRESH FORCE -- 最常用方式 ``` 2. **刷新触发机制** - `ON COMMIT`:基表提交时自动刷新 - `ON DEMAND`:手动执行刷新(默认) ```sql REFRESH FAST ON COMMIT -- 实时同步场景 ``` 3. **自动刷新计划** ```sql START WITH SYSDATE NEXT SYSDATE + INTERVAL '1' HOUR -- 每小时刷新 ``` #### 🧰 创建示例 ```sql -- 创建销售汇总物化视图(每小时自动刷新) CREATE MATERIALIZED VIEW sales_summary_mv BUILD IMMEDIATE REFRESH FORCE ON DEMAND START WITH SYSDATE NEXT SYSDATE + 1/24 AS SELECT product_id, SUM(quantity) total_qty, AVG(unit_price) avg_price FROM sales GROUP BY product_id; ``` #### 🚀 典型应用场景 1. **数据仓库加速** ```sql -- 预计算月销售聚合 CREATE MATERIALIZED VIEW monthly_sales_mv AS SELECT EXTRACT(MONTH FROM sale_date) month, SUM(amount) revenue FROM sales GROUP BY EXTRACT(MONTH FROM sale_date); ``` 2. **跨库数据同步** ```sql -- 远程数据库同步 CREATE MATERIALIZED VIEW remote_emp_mv REFRESH FAST ON COMMIT AS SELECT * FROM emp@remote_db; ``` 3. **复杂查询优化** ```sql -- 多表连接预计算 CREATE MATERIALIZED VIEW dept_salary_mv AS SELECT d.dname, AVG(e.sal) avg_sal FROM emp e JOIN dept d ON e.deptno=d.deptno GROUP BY d.dname; ``` #### ⚠️ 关键限制(Oracle/openGauss) 1. **DDL 限制** - 创建后基表不能执行 `DROP COLUMN`, `TRUNCATE` 等破坏性操作[^4] 2. **存储限制** - 不支持临时表/全局临时表创建[^4] 3. **刷新代价** ```sql -- 全量刷新可能锁表(需规划维护窗口) REFRESH MATERIALIZED VIEW sales_summary_mv COMPLETE; ``` #### 💡 最佳实践建议 1. **索引优化** ```sql CREATE INDEX idx_mv_sales ON sales_summary_mv(product_id); ``` 2. **增量刷新条件** - 基表需创建物化视图日志(Oracle) - 查询不能包含 `UNION`, `DISTINCT` 等非确定性操作[^2] 3. **空间管理** ```sql TABLESPACE large_data_ts -- 指定大表空间 ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值