版权声明:本文为CSDN博主「richieruan」的原创文章。
原文链接:https://blog.csdn.net/richieruan/article/details/44454033
基本定义
- 物化视图是包括一个查询结果的数据库对象,是一种特殊的物理表。
- 物化视图在某种意义上说就是一个物理表(而且不仅仅是一个物理表),这通过其可以被user_tables查询出来,而得到佐证;
- 物化视图也是一种段(segment),所以其有自己的物理存储属性;
- 物化视图会占用数据库磁盘空间,这点从user_segment的查询结果,可以得到佐证;
- 物化视图由于是物理真实存在的,故可以创建索引,创建方式和对普通表创建方式相同。
- 物化视图能够分为下面三种类型:包含聚集的物化视图。仅仅包含连接的物化视图;嵌套物化视图。三种物化视图的高速刷新的限制条件有非常大差别,而对于其它方面则差别不大。该点详见:http://blog.itpub.net/638844/viewspace-1062750/
- 特定场景中,利用物化视图可提高查询速度,但需要额外的存储空间;
- 基表有频繁的DML操作的时候不适合使用物化视图 / (on commit刷新时很费时,大大增加DML操作的时间)
- 多表连接的物化视图仅适合 refresh complete 定时刷新,且刷新时间不能小于30min,否则弊大于利(complete是删除原有数据重新连接多表数据)
物化视图与其他概念的区别
物化视图与普通表---两者都可以在user_objects查询到相关对象,但普通表一般存储原始数据即第一手生成数据、不依赖其他表,而物化视图的结果集多是复杂的多表连接查询结果,而且某些情况下,而原始表的的更新可以根据需要及时在物化视图上体现出来,普通表则不具备这种功能。
物化视图与普通视图的区别
普通视图并不在user_objects产生相应对象,只在数据库中建立查询定义且不具备降低资源消耗的功能,每次查询视图都要重新执行视图的定义,多数用于为远程登录用户提供数据只读查询的转换。
查询重写(Query Rewrite)
- 把一组用表或者视图表达的SQL语句,转换成用物化视图表示的SQL语句。这种转化对应用是透明的,它可以像索引一样被添加或删除,并且不会影响到应用代码。查询重写技术是Oracle的一项优化技术。
- 查询重写是指当对物化视图的基表进行查询时,Oracle会自己主动推断能否通过查询物化视图来得到结果,假设能够,则避免了聚集或连接操作。而直接从已经计算好的物化视图中读取数据。
- 默认DISABLE QUERY REWRITE。
- 设置语法:alter MATERIALIZED VIEW EMP_DEPT_MV_01 enable query rewrite;
- 详见:http://blog.itpub.net/28559081/viewspace-755285/
创建物化视图
语法:
create materialized view [view_name]
build immediate refresh [fast|complete|force] [ on [commit|demand] | start with (start_time) next (next_time) ] as {创建物化视图用的查询语句}
语法解释:
1.REFRESH [FAST|COMPLETE|FORCE] 视图刷新的方式:
- FAST: 增量刷新.假设前一次刷新的时间为T1,那么使用FAST模式刷新物化视图时,只向视图中添加T1到当前时间段内,主表变化过的数据.为了记录这种变化,建立增量刷新物化视图还需要一个物化视图日志表。CREATE MATERIALIZED VIEW LOG ON (主表名)。
- COMPLETE:全部刷新。相当于重新执行一次创建视图的查询语句。
- FORCE: 这是默认的数据刷新方式。当可以使用FAST模式时,数据刷新将采用FAST方式;否则使用COMPLETE方式。
2.数据刷新的时间:
- ON DEMAND:在用户需要刷新的时候刷新,这里就要求用户自己动手去刷新数据了(也可以使用JOB定时刷新)
- ON COMMIT:当主表中有数据提交的时候,立即刷新MV中的数据;
3.START ……:从指定的时间开始,每隔一段时间(由NEXT指定)就刷新一次;
4.数据初始方式
- BUILD IMMEDIATE是在创建物化视图的时候就生成数据,而
- BUILD DEFERRED则在创建时不生成数据,以后根据需要在生成数据。默认为BUILD IMMEDIATE。
删除物化视图
drop materialized view an_user_base_file_no_charge;
手动刷新物化视图
begin dbms_mview.refresh(TAB=>'an_user_base_file_no_charge', METHOD=>'COMPLETE', --'FAST'增量刷新 PARALLELISM=>8); --PARALLELISM并行控制参数 end; /
使用job刷新物化视图
begin dbms_scheduler.create_job( job_name => 'sam_job', --job名 job_type => 'STORED_PROCEDURE', --job类型 job_action => 'pc_sam', --存储过程名 start_date => sysdate, --开始执行时间 repeat_interval => 'FREQ=MINUTELY;INTERVAL=5', --下次执行时间,每5分钟执行存储过程pc_sam comments => '测试存储过程', --注释 auto_drop => false, --job禁用后是否自动删除 enabled => true); end; /
- job_name: 任务名称
- job_type:有三种类型,PL/SQL Block、Stored procedure、Executable
- job_action:根据job_type的不同,有不同的含义
- 如果job_type指定的是存储过程,就需要指定存储过程的名字;
- 如果job_type指定的是PL/SQL块,就需要输入完整的PL/SQL代码;
- 如果job_type指定的外部程序,就需要输入script的名称或者操作系统的指令名
- start_date:开始时间
- repeat_interval:运行的时间间隔,上面例子是每天23点运行一次
- end_date:到期时间
- enabled:创建后自动激活
- auto_drop:默认true,即当job执行完毕都到期是否直接删除job
- comments:备注
创建物化视图日志
Oracle 的物化视图的快速刷新要求必须建立物化视图日志,通过物化视图日志可以实现增量刷新功能。
- 物化视图日志在建立时的增量一句有多种选项:可以指定为ROWID、PRIMARY KEY和OBJECTID几种类型,同时还可以指定SEQUENCE或明确指定列名。不过上面这些情况产生的物化视图日志的结构都不相同。
- 当发生DML(insert、update、delete) 操作时,内部的触发器会把变化记录到物化视图日志里,也就是说物化视图不支持DDL(create、drop、alert)的同步,所以在物化视图的编写过程中不可使用select * from 的形式,因为这样当基表发生变化时,物化视图就会失效。
创建语法:
create materialized view log on 物化视图名称/表名 with primary key,sequence (name, num) including new values;
DROP MATERIALIZED VIEW a;
- 如果WITH后面跟了ROWID,则物化视图日志中会包含:M_ROW$$:用来存储发生变化的记录的ROWID。
- 如果WITH后面跟了PRIMARY KEY,则物化视图日志中会包含主键列。
- 如果WITH后面跟了OBJECT ID,则物化视图日志中会包含:SYS_NC_OID$:用来记录每个变化对象的对象ID。
- 如果WITH后面跟了SEQUENCE,则物化视图日子中会包含:SEQUENCE$$:给每个操作一个SEQUENCE号,从而保证刷新时按照顺序进行刷新。
- 如果WITH后面跟了一个或多个COLUMN名称,则物化视图日志中会包含这些列。
查询日志语句:
select * from mlog$_物化视图名称/表名;
- SNAPTIME$$:用于表示刷新时间。
- DMLTYPE$$:用于表示DML操作类型,I表示INSERT,D表示DELETE,U表示UPDATE。
- OLD_NEW$$:用于表示这个值是新值还是旧值。N(EW)表示新值,O(LD)表示旧值,U表示UPDATE操作。
- CHANGE_VECTOR$$:表示修改矢量,用来表示被修改的是哪个或哪几个字段。Oracle就是通过CHANGE_VECTOR$$列来记录每条记录发生变化的字段包括哪些。
including new values
- 我们创建物化视图日志的时候还可以带上including new values,该子句允许Oracle数据库将新旧值都保存在物化视图日志中,以便更新DML操作。
物化视图的增量刷新
总结一下创建fast模式物化视图条件:
- 多表连接的物化视图想要使用fast刷新时,
- 首先,select 语句中包含到的每一个表都需要创建视图日志;
- 其次,视图日志中需要指定在select语句和where条件中用到的该表的字段;
- 第三,在select中必须包含所涉及到的所有表的rowid,
- 第四,外连接不能使用标志sql语法,应使用(+)这种oracle固有语法.
- 当然还有很多其他的限制条件,可以参考:https://blog.csdn.net/aiyocxuan/article/details/78732567
使用物化视图增量刷新的优缺点
- 使用增量模式刷新物化视图的优点就是不需要对整个物化视图进行刷新,当物化视图的数据特别大的时候可以减少刷新的时间,其他的优点没有暂时还没感受到。
缺点:
- 使用增量模式进行刷新需要对所有关联的基表都建立物化视图日志,首先在数据库中就要占据一部分的空间,其次对基表创建物化视图日志对基表的DML还是有影响的,可以参考下面:
Oracle 物化视图快速刷新对性能的影响
- http://blog.itpub.net/28539951/viewspace-2127870/
- 然后对基表的DML和对物化视图日志的更新应该是在同一个事务里的,因为rollback的时候是会一起rollback的,所以如果物化视图日志一旦失败可能导致基表的DML操作失败,对业务上可能会影响。
- 物化视图日志的维护成本比较高
- 物化视图日志经常会由于物化视图长时间没有刷新,或者基表的一次批量数据更改而变得很大,这会影响物化视图的刷新性能,因此对于这种情况需要对物化视图日志进行处理,降低物化视图日志表的高水位线。
- Oracle的物化视图的快速刷新功能,主要是靠物化视图日志来实现的。
- 物化视图日志会记录下基表所有的增、删、改操作,而物化视图执行完快速刷新操作后,会从物化视图日志中将本物化视图刷新过且其他物化视图所不需要刷新的记录删除掉。如果其中一个物化视图一直不刷新,那么物化视图日志就会变得越来越大。
- 还有一种情况,比如表中插入了大量的数据,或者删除了大量的数据,或者将表中的某一列统一更新为一个值,这种操作都会在物化视图日志中产生大量的记录。
- 而物化视图日志的增大必然影响物化视图的刷新速度。一方面,物化视图在刷新的时候要扫描物化视图日志,另一方面,物化视图在刷新结束后,也要清除物化视图日志中的记录,仍然要扫描物化视图日志,因此物化视图日志的大小直接会影响物化视图快速刷新的速度。更重要的是,物化视图日志的高水位一旦增长到一个很高的位置,即使以后物化视图日志中记录很少,甚至没有记录存在,物化视图在刷新的时候仍然需要较长的时间。