Oracle物化视图学习笔记

物化视图是一种特殊的物理表,“物化”(Materialized)视图是相对普通视图而言的。普通视图是虚拟表,应用的局限性大,任何对视图的查询,Oracle都实际上转换为视图SQL语句的查询。这样对整体查询性能的提高,并没有实质上的好处。

直接刷新

 

在scott用户下创建源数据表

create table scott.emp_ori
  as
  select empno, deptno,sal
  from scott.emp

 

在ceno用户下创建MV

create materialized view ceno.mv_emp
build immediate
refresh on commit
--enable query rewrite
as
select empno, deptno,sal
from scott.emp

 

现在在源头数据表scott.ori作dml操作

 

drop table scott.emp_ori purge

 

create table scott.emp_ori

as

select empno, deptno,sal

from scott.emp where empno<2000

 

select * from scott.emp_ori

 

drop  materialized view ceno.mv_emp

 

create materialized view ceno.mv_emp

build immediate

refresh on commit

enable query rewrite

as

select empno, deptno,sal

from scott.emp_ori

 

ORA-12054: 无法为实体化视图设置 ON COMMIT 刷新属性

 

alter table scott.emp_ori add constraintpk_emp_ori primary key (empno)

 

create materialized view ceno.mv_emp

build immediate

refresh on commit

enable query rewrite

as

select empno, deptno,sal

from scott.emp_ori

 

 

ok --成功创建  建立refresh on commit 需要源表上有主键存在? 等一会儿再进行讨论

 

看看原表与mv的数据

select empno,deptno,sal, '源数据' date_source  from scott.emp_ori

union all

select empno,deptno,sal,  '目标数据'  date_source fromceno.mv_emp

 

无数据

 

insert into scott.emp_ori select

 

 

对源表进行DML操作

 

insert into scott.emp_ori

 select empno, deptno,sal

 from scott.emp where empno<7400

 

 select empno,deptno,sal, '源数据' date_source  from scott.emp_ori

union all

select empno,deptno,sal,  '目标数据'  date_source fromceno.mv_emp

 

commit;

 

select empno,deptno,sal, '源数据' date_source  from scott.emp_ori

union all

select empno,deptno,sal,  '目标数据'  date_source fromceno.mv_emp

 

update scott.emp_ori set sal=600

 

select empno,deptno,sal, '源数据' date_source  from scott.emp_ori

union all

select empno,deptno,sal,  '目标数据'  date_source fromceno.mv_emp

 

commit;

 

delete from scott.emp_ori

 

select empno,deptno,sal, '源数据' date_source  from scott.emp_ori

union all

select empno,deptno,sal,  '目标数据'  date_source fromceno.mv_emp

 

commit;

 

select empno,deptno,sal, '源数据' date_source  from scott.emp_ori

union all

select empno,deptno,sal,  '目标数据'  date_source fromceno.mv_emp

 

merge into scott.emp_ori t

using (select empno,deptno,sal   from scott.emp where empno<7600) s

on (t.empno=s.empno)

when matched then

update set t.deptno=s.deptno, t.sal=s.sal

when not matched then

insert (t.empno,t.deptno,t.sal)

values(s.empno,s.deptno,s.sal)

 

 

select empno,deptno,sal, '源数据' date_source  from scott.emp_ori

union all

select empno,deptno,sal,  '目标数据'  date_source fromceno.mv_emp

 

commit;

 

select empno,deptno,sal, '源数据' date_source  from scott.emp_ori

union all

select empno,deptno,sal,  '目标数据'  date_source fromceno.mv_emp

 

看到源数据与目标数据在提交后,立即被一致化。

 

 

之前,我们说了,数据库commit实际上并没有多少工作要做,那怕之前的事物是一个很大的事物,commit也是瞬间完成工作。

 

但是有时候,提交却要需要很长时间,最有可能的原因是可能有一个MV建立在该表上,需要较长的时间将变化数据刷新到目标物化视图。

 

检查一张表上是否有物化视图

因为query是long类型的字段,所以不能用以下方法来检查

select * from all_mviews wherelower(to_lob(query)) like '%scott.emp_ori%'

 

采用以下方法

create table mv_info

(

owner varchar2(32),

mview_name varchar2(30),

query clob

)

 

insert into mv_info

select owner,mview_name,to_lob(query)  from all_mviews

 

select * from mv_info where lower(query)like '%scott.emp_ori%'

 

疑问 这个选项如何能够影响到源表的行为

 

看看这个物化视图的完整脚本

 CREATE MATERIALIZED VIEW "CENO"."MV_EMP"

 ORGANIZATION HEAP

 PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING

 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)

 TABLESPACE "USERS"

 BUILD IMMEDIATE

 USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255

 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)

 TABLESPACE "USERS"

 REFRESH FORCE ON COMMIT

 WITH PRIMARY KEY

 USING DEFAULT LOCAL ROLLBACK SEGMENT

 USING ENFORCED CONSTRAINTS ENABLE QUERY REWRITE

  ASselect empno, deptno,sal

 from scott.emp_ori

 

隐藏在MV之后的一些问题

SQL> desc MV_EMP

Name  Type        Nullable DefaultComments

------ ----------- -------- ---------------

EMPNO NUMBER(4)                            

DEPTNO NUMBER(2)   Y                        

SAL   NUMBER(7,2) Y

 

现在我们改变表名

conn scott/tiger@gq

rename emp_ori to emp_ori1

 

再查看MV_EMP的脚本,发现依然还是使用emp_ori表,这和依赖于emp_ori其它的对象不一样。

 

explain plan for

select * from mv_emp  where empno=7369

 

 

select * from table(dbms_xplan.display())

---------------------------------------------------------------------------------------------

| Id  |Operation                      |Name       | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------------------------

|   0 | SELECTSTATEMENT               |            |     1 |   39 |     1   (0)| 00:00:01|

|   1 |  MAT_VIEW ACCESS BY INDEX ROWID| MV_EMP     |    1 |    39 |     1  (0)| 00:00:01 |

|*  2 |   INDEX UNIQUE SCAN            | PK_EMP_ORI |     1 |      |     1   (0)| 00:00:01|

---------------------------------------------------------------------------------------------

 

selectdbms_metadata.get_ddl('INDEX','PK_EMP_ORI') from dual

 

 CREATE UNIQUE INDEX "CENO"."PK_EMP_ORI" ON"CENO"."MV_EMP" ("EMPNO")

 PCTFREE 10 INITRANS 2 MAXTRANS 255

 STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)

 TABLESPACE "USERS"

 

我们并没有在MV_EMP的empno上建立唯一性索引,它是建立MV的时候自动建立上的。

 

修改原表的名称

 

rename emp_ori to emp_ori1

 

create table emp_ori as

select * from emp_ori1

 

select * from emp_ori

 

insert into emp_ori values(1000,20,12)

commit;

 

没有看到mv_emp变化

 

alter table scott.emp_ori add constraint pk_emp_ori1primary key (empno) ;

insert into emp_ori values(2000,20,12);

commit;

 

没有看到mv_emp变化

 

重新建立mv_emp后,才会看到mv有了刷新机制

 

 

select * from user_mviews

 

rename emp_ori to emp_ori2

 

rename emp_ori1 to emp_ori

insert into emp_ori values(2000,20,12);

commit;

 

也没有看到MV_emp的变化

 

修改表名城前后

观察select *from user_mview

OWNER

CENO

CENO

MVIEW_NAME

MV_EMP

MV_EMP

CONTAINER_NAME

MV_EMP

MV_EMP

QUERY

QUERY_LEN

44

44

UPDATABLE

N

N

UPDATE_LOG

MASTER_ROLLBACK_SEG

MASTER_LINK

REWRITE_ENABLED

Y

Y

REWRITE_CAPABILITY

GENERAL

GENERAL

REFRESH_MODE

COMMIT

COMMIT

REFRESH_METHOD

FORCE

FORCE

BUILD_MODE

IMMEDIATE

IMMEDIATE

FAST_REFRESHABLE

DML

DML

LAST_REFRESH_TYPE

COMPLETE

COMPLETE

LAST_REFRESH_DATE

2009-1-8 21:41

2009-1-8 21:41

STALENESS

FRESH

COMPILATION_ERROR

AFTER_FAST_REFRESH

NA

NA

UNKNOWN_PREBUILT

N

N

UNKNOWN_PLSQL_FUNC

N

N

UNKNOWN_EXTERNAL_TABLE

N

N

UNKNOWN_CONSIDER_FRESH

N

N

UNKNOWN_IMPORT

N

N

UNKNOWN_TRUSTED_FD

N

N

COMPILE_STATE

VALID

COMPILATION_ERROR

USE_NO_INDEX

N

N

STALE_SINCE

NUM_PCT_TABLES

0

0

NUM_FRESH_PCT_REGIONS

NUM_STALE_PCT_REGIONS

 

 

create materialized view ceno.mv_sum_emp

build immediate

refresh on commit

enable query rewrite

as

select deptno,sum(sal) sal

from scott.emp_ori

group by deptno

 

explain plan for

select deptno,sum(sal) sal

from scott.emp_ori

group by deptno

 

select * from table(dbms_xplan.display())

-------------------------------------------------------------------------------------------

| Id  |Operation                    | Name       | Rows | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------------------

|   0 | SELECTSTATEMENT             |            |    2|    52 |     3  (0)| 00:00:01 |

|   1 |  MAT_VIEW REWRITEACCESS FULL| MV_SUM_EMP |     2 |    52 |    3   (0)| 00:00:01 |

-------------------------------------------------------------------------------------------

 

explain plan for

select /*+norewrite*/deptno,sum(sal)sal

from scott.emp_ori

group by deptno

 

select * from table(dbms_xplan.display())

------------------------------------------------------------------------------

| Id  |Operation          | Name    | Rows | Bytes | Cost (%CPU)| Time     |

------------------------------------------------------------------------------

|   0 | SELECTSTATEMENT   |         |    2 |    14 |     4 (25)| 00:00:01 |

|   1 |  HASH GROUP BY     |        |     2 |    14 |    4  (25)| 00:00:01 |

|   2|   TABLE ACCESS FULL| EMP_ORI |     5 |   35 |     3   (0)| 00:00:01|

------------------------------------------------------------------------------

 

为什么说 查询重写技术比累积表要强大很多?

 

select deptno,sum(sal) sal
from scott.emp_ori
group by deptno

DEPTNO

SAL

30

2850

20

3787

 

insert into scott.emp_ori
select empno+1000, deptno,sal from scott.emp_ori
 
select deptno,sum(sal) sal
from scott.emp_ori
group by deptno

 

DEPTNO

SAL

30

5700

20

7574

 

explain plan for

select deptno,sum(sal) sal

from scott.emp_ori

group by deptno

 

select * from table(dbms_xplan.display())

-------------------------------------------------------------------------------------------

| Id  |Operation                    | Name       | Rows | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------------------

|   0 | SELECTSTATEMENT             |            |     2 |   52 |     3   (0)| 00:00:01|

|   1 |  MAT_VIEW REWRITE ACCESS FULL| MV_SUM_EMP|     2 |    52 |    3   (0)| 00:00:01 |

-------------------------------------------------------------------------------------------

 

 

 

update MV_SUM_EMP set sal=sal+100

 

ORA-01732: 此视图的数据操纵操作非法

 

 

以上流程很好地建立数据复制,但是有以下一些问题

1、 如果不需要同步更新(原因)

2、 分区表建立主键很不方便

3、 不是每一张表都可以建立主键的

4、如果只关心部分数据变化

 

为了解决以上问题,oracle提供了mv_log

 

 

 

 

 

 

CREATE TABLE emp_hash_p

 (

empno number(4),

deptno number(4),

sal number(16,2)

 )

 PARTITION BY HASH (empno) partitions 4

 

drop  materialized view ceno.mv_emp

 

create materialized view mv_p_emp

build immediate

refresh on commit

enable query rewrite

as

select empno, deptno,sal

from emp_hash_p



 原创文章,如果转载,请标注作者:田文  CSDN地址:http://blog.csdn.net/tiwen818


你可能感兴趣的:(数据库)