通过案例学调优之--跨库建立物化视图(Materialized View)
应用环境:
操作系统: RedHat EL55
Oracle: Oracle 10gR2
Oracle的物化视图是包括一个查询结果的数据库对像,它是远程数据的的本地副本,或者用来生成基于数据表求和的汇总表。物化视图存储基于远程表的数据,也可以称为快照。
物化视图可以用于预先计算并保存表连接或聚集等耗时较多的操作的结果,这样,在执行查询时,就可以避免进行这些耗时的操作,而从快速的得到结果。物化视图有很多方面和索引很相似:使用物化视图的目的是为了提高查询性能;物化视图对应用透明,增加和删除物化视图不会影响应用程序中SQL语句的正确性和有效性;物化视图需要占用存储空间;当基表发生变化时,物化视图也应当刷新。
物化视图可以查询表,视图和其它的物化视图。
通常情况下,物化视图被称为主表(在复制期间)或明细表(在数据仓库中)。
对于复制,物化视图允许你在本地维护远程数据的副本,这些副本是只读的。如果你想修改本地副本,必须用高级复制的功能。当你想从一个表或视图中抽取数据时,你可以用从物化视图中抽取。
对于数据仓库,创建的物化视图通常情况下是聚合视图,单一表聚合视图和连接视图。
在复制环境下,创建的物化视图通常情况下主键,rowid和子查询视图。
物化视图由于是物理真实存在的,故可以创建索引。
二、物化视图刷新
1) 按刷新方式分:FAST/COMPLETE/FORCE
2) 按刷新时间的不同:ON DEMAND/ON COMMIT
3) 按是否可更新:UPDATABLE/READ ONLY
4) 按是否支持查询重写:ENABLE QUERY REWRITE/DISABLEQUERY REWRITE
默认情况下,如果没指定刷新方法和刷新模式,则Oracle默认为FORCE和DEMAND。
注意:设置REFRESH ON COMMIT的物化视图不能访问远端对象。
在建立物化视图的时候可以指定ORDER BY语句,使生成的数据按照一定的顺序进行保存。不过这个语句不会写入物化视图的定义中,而且对以后的刷新也无效。
1) 完全刷新(COMPLETE)会删除表中所有的记录(如果是单表刷新,可能会采用TRUNCATE的方式),然后根据物化视图中查询语句的定义重新生成物化视图。
2) 快速刷新(FAST)采用增量刷新的机制,只将自上次刷新以后对基表进行的所有操作刷新到物化视图中去。FAST必须创建基于主表的视图日志。
对于增量刷新选项,如果在子查询中存在分析函数,则物化视图不起作用。
3) 采用FORCE方式,Oracle会自动判断是否满足快速刷新的条件,如果满足则进行快速刷新,否则进行完全刷新。
Oracle物化视图的快速刷新机制是通过物化视图日志完成的。Oracle通过一个物化视图日志还可以支持多个物化视图的快速刷新。
物化视图日志根据不同物化视图的快速刷新的需要,可以建立为ROWID或PRIMARY KEY类型的。还可以选择是否包括SEQUENCE、INCLUDING NEW VALUES以及指定列的列表。
三、创建物化视图命令
create materialized view [view_name]
refresh [fast|complete|force]
[
on [commit|demand] |
start with (start_time) next (next_time)
]
as
{创建物化视图用的查询语句}
案例分析:
本案例架构
1)在test1库上建立db link
tnsnames.ora:
[oracle@rh6 admin]$ cat tnsnames.ora # tnsnames.ora Network Configuration File: /u01/app/oracle/product/11.2.0/db_1/network/admin/tnsnames.ora # Generated by Oracle configuration tools. TEST1 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rh6.cuug.net)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = test1) ) ) PROD = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = rh6.cuug.net)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = prod) ) )
在prod库上建立tom用户,并授权 15:18:08 SYS@ prod >create user tom identified by tom; User created. 15:18:27 SYS@ prod >grant connect,resource to tom; Grant succeeded. 15:18:49 SYS@ prod >grant all on scott.emp1 to tom; Grant succeeded. 在test1库上建立db link 15:12:12 SYS@ test1 >grant create database link,create public database link to tom; Grant succeeded. 15:13:59 TOM@ test1 >create database link db_link_prod connect to tom identified by tom using 'prod'; Database link created. 测试: 15:19:10 TOM@ test1 >select * from scott.emp1@db_link_prod; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- ------------------- -------- 7369 SMITH CLERK 7902 1980-12-17 00:00:00 800 20 7499 ALLEN SALESMAN 7698 1981-02-20 00:00:00 1600 300 30 7521 WARD SALESMAN 7698 1981-02-22 00:00:00 1250 500 30 7566 JONES MANAGER 7839 1981-04-02 00:00:00 2975 20 7654 MARTIN SALESMAN 7698 1981-09-28 00:00:00 1250 1400 30 7698 BLAKE MANAGER 7839 1981-05-01 00:00:00 2850 30 7782 CLARK MANAGER 7839 1981-06-09 00:00:00 2450 10 7788 SCOTT ANALYST 7566 1987-04-19 00:00:00 3000 20 7839 KING PRESIDENT 1981-11-17 00:00:00 5000 10 7844 TURNER SALESMAN 7698 1981-09-08 00:00:00 1500 0 30 7876 ADAMS CLERK 7788 1987-05-23 00:00:00 1100 20 7900 JAMES CLERK 7698 1981-12-03 00:00:00 950 30 7902 FORD ANALYST 7566 1981-12-03 00:00:00 3000 20 7934 MILLER CLERK 7782 1982-01-23 00:00:00 1300 10 14 rows selected.
2)在prod库的emp1表上建立物化视图日志
15:06:49 SCOTT@ prod >create table emp1 as select * from emp; Table created. 15:09:07 SCOTT@ prod >alter table emp1 add constraint pk_emp1 primary key(empno); Table altered. 15:09:26 SCOTT@ prod >create materialized view log on emp1; Materialized view log created.
3)在test1上建立物化视图
在prod库上对tom授权 15:19:07 SYS@ prod >grant select any table to tom; Grant succeeded. 在test1库上对tom授权 15:22:11 SYS@ test1 >grant create materialized view to tom; Grant succeeded. TOM@ test1 >create materialized view mv1_emp1 refresh fast on demand as select * from scott.emp1@db_link_prod; 测试: 15:33:15 TOM@ test1 >select * from mv1_emp1; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- ------------------- -------- 7369 SMITH CLERK 7902 1980-12-17 00:00:00 800 20 7499 ALLEN SALESMAN 7698 1981-02-20 00:00:00 1600 300 30 7521 WARD SALESMAN 7698 1981-02-22 00:00:00 1250 500 30 7566 JONES MANAGER 7839 1981-04-02 00:00:00 2975 20 7654 MARTIN SALESMAN 7698 1981-09-28 00:00:00 1250 1400 30 7698 BLAKE MANAGER 7839 1981-05-01 00:00:00 2850 30 7782 CLARK MANAGER 7839 1981-06-09 00:00:00 2450 10 7788 SCOTT ANALYST 7566 1987-04-19 00:00:00 3000 20 7839 KING PRESIDENT 1981-11-17 00:00:00 5000 10 7844 TURNER SALESMAN 7698 1981-09-08 00:00:00 1500 0 30 7876 ADAMS CLERK 7788 1987-05-23 00:00:00 1100 20 7900 JAMES CLERK 7698 1981-12-03 00:00:00 950 30 7902 FORD ANALYST 7566 1981-12-03 00:00:00 3000 20 7934 MILLER CLERK 7782 1982-01-23 00:00:00 1300 10 14 rows selected.
4)测试物化视图数据刷新
在基表上更新数据 15:33:10 SYS@ prod >conn scott/tiger Connected. 15:35:59 SCOTT@ prod >select * from emp1 where empno=7788; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- --------- ---------- ------- 7876 ADAMS CLERK 7788 23-MAY-87 1100 20 15:36:04 SCOTT@ prod >update emp1 set deptno=40 where empno=7788; 1 row updated. 15:36:23 SCOTT@ prod >commit; Commit complete. 15:36:35 SCOTT@ prod >select * from emp1 where empno=7788; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- --------- ---------- ------- 7788 SCOTT ANALYST 7566 19-APR-87 3000 40 在物化视图上查看数据更新 15:35:13 TOM@ test1 >select * from mv1_emp1 where empno=7788; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- ------------------- -------- 7788 SCOTT ANALYST 7566 1987-04-19 00:00:00 3000 20 默认物化视图不会自动更新,需手工更新 15:38:12 TOM@ test1 >exec dbms_mview.refresh('mv1_emp1','fast'); PL/SQL procedure successfully completed. 15:38:41 TOM@ test1 >select * from mv1_emp1 where empno=7788; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- ------------------- -------- 7788 SCOTT ANALYST 7566 1987-04-19 00:00:00 3000 40
至此,物化视图建立完成 !
5)查看数据和日志更新信息
在test1上查看数据刷新信息 15:39:02 TOM@ test1 >select mview_name, last_refresh_date, staleness from user_mviews; MVIEW_NAME LAST_REFRESH_DATE STALENESS ------------------------------ ------------------- ------------------- MV1_EMP1 2014-08-22 15:38:41 UNDEFINED 在prod上查看物化视图日志更新信息 15:40:41 SCOTT@ prod >select log_owner,master,log_table,PRIMARY_KEY,LAST_PURGE_DATE,LAST_PURGE_STATUS from user_mview_logs LOG_OWNER MASTER LOG_TABLE PRI LAST_PURG LAST_PURGE_STATUS ------------------------------ ------------------------------ --------- SCOTT EMP1 MLOG$_EMP1 YES 22-AUG-14 0
6)在物化视图上创建索引
15:39:39 TOM@ test1 >CREATE index mv1_ind on mv1_emp1(ename) tablespace indx; Index created. 16:39:15 TOM@ test1 >select index_name,index_type,table_name,BLEVEL,leaf_blocks FROM user_indexes 16:39:30 2 where index_name='MV1_IND'; INDEX_NAME INDEX_TYPE TABLE_NAME BLEVEL LEAF_BLOCKS ------------------------------ --------------------------- ------------ MV1_IND NORMAL MV1_EMP1 0 1 16:40:02 TOM@ test1 >select * from mv1_emp1 where ename='scott'; no rows selected Elapsed: 00:00:00.02 Execution Plan ---------------------------------------------------------- Plan hash value: 720877713 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 87 | 1 (0)| 00:00:01 | | 1 | MAT_VIEW ACCESS BY INDEX ROWID| MV1_EMP1 | 1 | 87 | 1 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | MV1_IND | 1 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("ENAME"='scott') Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 310 recursive calls 0 db block gets 44 consistent gets 0 physical reads 0 redo size 695 bytes sent via SQL*Net to client 408 bytes received via SQL*Net from client 1 SQL*Net roundtrips to/from client 2 sorts (memory) 0 sorts (disk) 0 rows processed
案例错误信息:
建立物化视图出错
15:31:27 TOM@ test1 >create materialized view mv1_emp1
15:32:36 2 refresh fast on demand
15:32:36 3 as
15:32:36 4 select * from scott.emp1@db_link_prod;
create materialized view mv1_emp1
*
ERROR at line 1:
ORA-12018: following error encountered during code generation for "TOM"."MV1_EMP1"
ORA-00942: table or view does not exist
解决:
在基表所在的库上,进行授权:
15:19:07 SYS@ prod >grant select any table to tom;
Grant succeeded.