您的位置:首页 > 数据库 > Oracle

Expert One-on-One Oracle Chapter 13 物化视图 读书笔记(3)

2008-03-24 20:39 585 查看
物化视图的最大的优势是可以提高性能:通过预先计算好答案存储起来,可以大大地减少机器的负载。
特点如下:
更少的物理读--扫描更少的数据
更少的写--不用经常排序和聚集
减少CPU的消耗--不用对数据进行聚集计算和函数调用
显著地加快响应时间--在使用物化视图查询数据时(与主表相反),将会很快的返回查询结果

物化视图会增加对磁盘资源的需求,即需要永久分配的硬盘空间给物化视图来存储数据。
物化视图用于只读或者“精读”环境下工作最好 ,不用于联机事务处理系统(OLTP)环境。

下面讲物化视图是如何工作的?
假设创建了一个物化视图,并且知道该物化视图有了某个问题的答案,但是由于某些原因,oracle没有这样做。
为什么ORACLE不会知道使用物化视图可以知道答案?
是因为oralce他不知道一些信息,一些能够告诉它获取我们想要的信息的信息。
oracle只是一个软件,她仅仅能对提供给它的信息进行处理。提供的元数据越多,给oracle有关潜在的数据的信息越读,则越好。这些信息
可能是一些约束,主键,外键等等。

下面将讲些例子来说明物化视图必须做什么,以及提供给它信息物化视图将会如何会用的更多。
物化视图的设置:
系统级:通过INIT.ORA
会话级:通过alter session命令
设置参数如下:
query_rewrite_enabled--此参数设置为true,则表示会发生查询重写;当为false,则不会发生查询重写;
query_rewrite_integrity--此参数是控制oracle如何重写查询,且可能设置为下面的三种值:
enforced--仅仅使那些由oracle强迫和保证的约束以及规则的查询可以重写;
但由于oralce不强加一些可以通过oralce知道其他的推论关系的查询的关系;
trusted--使用oralce强加的约束,以及任意关系存在于数据中的而非数据库强加的关系可以重写查询;
stale_tolerated-使用物化视图可以重写查询,即使oralce知道包含的数据是陈旧的。

query_rewrite_enabled=false,oracle对SQL语句进行分析与优化;
query_rewrite_enabled=true,oracle通过起用查询重写功能,在分析过SQL语句之后,oracle将多一个步骤重写此查询以访问某些物化视图,而不是它所参照的真正的表。
如果能够执行查询重写,这些重写的查询就被分析,并与初始查询一起优化,从数据字典所发现的可利用的物化视图的集合中执行成本最低
的查询方案,这样的查询成本最低;
如果不能重写此查询,就对原始分析的查询进行优化,并正常运行;
1、查询重写的步骤:
完全精确的正文匹配->部分正文匹配->一般查询重写方法(要求数据充足并且连接兼容)->分组兼容性->聚集兼容性

2、如何确保物化视图可以使用?
这里只讲三种方法来帮助使用物化视图的查询重写功能:
1)约束;
2)维数;
3)描述复杂关系-数据层次结构;

下面是对上面三种方法举例说明:
1)约束:
SQL> create table emp as select * from scott.emp;
Table created.
Elapsed: 00:00:06.41
SQL> create table dept as select * from scott.dept;
Table created.
Elapsed: 00:00:01.02

SQL>grant query rewrite to test;
Grant succeeded.
Elapsed: 00:00:01.06

SQL> alter session set query_rewrite_enabled=true;
Session altered.
Elapsed: 00:00:00.22

SQL> alter session set query_rewrite_integrity=enforced;
Session altered.
Elapsed: 00:00:00.01

SQL> create materialized view emp_dept
2 build immediate
3 refresh on demand
enable query rewrite
4 5 as
6 select dept.deptno, dept.dname, count (*)
7 from emp, dept
8 where emp.deptno = dept.deptno
9 group by dept.deptno, dept.dname;

SQL> alter session set optimizer_goal=all_rows;
Session altered.
Elapsed: 00:00:00.05
(注:All Rows:也就是我们所说的Cost的方式,当一个表有统计信息时,它将以最快的方式返回表的所有的行,从总体上提高查询的吞吐量。
没有统计信息则走基于规则的方式。)

此时oralce并不知道EMP表和DEPT表之间的饿关系,不知道哪一列是住码等。
SQL> set autotrace on

SQL> select count(*) from emp;

COUNT(*)
----------
14

Elapsed: 00:00:03.29

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=327)

Statistics
----------------------------------------------------------
6 recursive calls
0 db block gets
11 consistent gets
0 physical reads
0 redo size
379 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
1 rows processed

实质上面的SQL语句是可以采用查询重写中的分组兼容性步骤来实现采用物化视图来查询,因为此时可以很容易的从物化视图中获取信息;
但是oralce不知道emp与dept表之间的关系,emp表中的每个员工都上属于DEPT表中的部门,所以oracle没有采用物化视图。
需要我们告诉oralce,下面是告知oracle emp表和 DEPT表之间的关系:
SQL> alter table dept
add constraint dept_pk primary key(deptno); 2 --告诉oracle deptno字段是dept表的主码

Table altered.

Elapsed: 00:00:03.54
SQL> alter table emp --告诉oracle emp表中的deptno字段是一个外码,与dept表中的deptno有对应关系
add constraint emp_fk_dept
2 3 foreign key(deptno) references dept(deptno);

Table altered.

Elapsed: 00:00:00.81
SQL> alter table emp modify deptno not null; --告诉oracle emp表中的deptno字段是不为空的

Table altered.

Elapsed: 00:00:00.24

告诉oracle这些信息之后,再执行select count(*) from emp语句:
SQL> set autotrace on
SQL> select count(*) from emp;

COUNT(*)
----------
14

Elapsed: 00:00:01.20

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1 Bytes=13)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'EMP_DEPT' (Cost=2 Card=327 Bytes
=4251)

Statistics
----------------------------------------------------------
315 recursive calls
36 db block gets
85 consistent gets
0 physical reads
6864 redo size
379 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
11 sorts (memory)
0 sorts (disk)
1 rows processed

从上面的执行计划中看出此时oracle采用了物化视图来查询,oracle能够进行查询重写;

上面的例子是要求要告诉oracle数据库emp表和dept表之间的约束关系,但是有时候不想在另外花力气来核实这个外码的关系,
已经在数据净化例程中做了这件事(什么叫数据净化?在数据仓库的组成中有一个叫“数据抽数据净化数据载入”,可能就是这
里提到的数据净化,意思可能就是在数据被载入到数据库之前,已经进行了数据的净化,不会有数据不完整性的情况存在)。
下面举例来模拟这个数据装入数据库的过程,
先已经对数据进行的了净化,然后丢掉约束,装入数据,刷新物化视图,最后再将约束加进去。
先从丢掉约束开始:
SQL> alter table emp drop constraint emp_fk_dept;

Table altered.

SQL> alter table dept drop constraint dept_pk;

Table altered.

SQL> alter table emp modify deptno null;

Table altered.

下面是装入数据过程,假设装入了一条数据:
SQL> insert into emp (empno,deptno) values ( 1, 1 );

1 row created.

SQL> commit;

Commit complete.

下面是告诉oracle刷新物化视图:
SQL> exec dbms_mview.refresh( 'EMP_DEPT' );

PL/SQL procedure successfully completed.

这个时候告诉oracle有关emp和dept表之间的关系:
SQL> alter table dept
add constraint dept_pk primary key(deptno)
2 3 rely enable NOVALIDATE ;

Table altered.

SQL> alter table emp
add constraint emp_fk_dept
foreign key(deptno) references dept(deptno)
rely enable NOVALIDATE 2 3 4 ;

Table altered.

SQL> alter table emp modify deptno not null NOVALIDATE;

Table altered.

上面的语句中有rely enable NOVALIDATE以及NOVALIDATE表示告诉oracle不必不再对装入的已有数据的检查,并且rely告诉oracle要相信
数据的完整性,即告知oracle相信如果将emp和dept表连起来, 将检索emp表的每一行。
事实上对oracle说的并不是事实,有一条新插入emp的数据在dept中并没有对应的行,违反了数据的完整性。
如果设置alter session set query_rewrite_integrity=enforced;
则下面:
SQL> alter session set query_rewrite_integrity=enforced;

Session altered.

Elapsed: 00:00:00.00
SQL> select count(*) from emp;

COUNT(*)
----------
15

Elapsed: 00:00:00.40

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=654)

Statistics
----------------------------------------------------------
288 recursive calls
38 db block gets
77 consistent gets
0 physical reads
6752 redo size
379 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
9 sorts (memory)
0 sorts (disk)
1 rows processed

分析:当query_rewrite_integrity=enforced时,只有使那些由oracle强迫
和保证的约束以及规则的查询才可以重写 ,上面尽管建了约束,但是这个约束并没有
核实,而且并没有被数据库自己所确认,所以该语句并没有查询重写rely enable NOVALIDATE以及NOVALIDATE
表示告诉oracle不必不再对装入的已有数据的检查,实质就是数据库自己并没有确认,所以并不是
由oracle强迫和保证的约束以及规则的查询

SQL> alter session set query_rewrite_integrity=trusted;

Session altered.

SQL> select count(*) from emp;

COUNT(*)
----------
14

Elapsed: 00:00:00.30

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1 Bytes=13)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'EMP_DEPT' (Cost=2 Card=82 Bytes=
1066)

Statistics
----------------------------------------------------------
20 recursive calls
1 db block gets
17 consistent gets
1 physical reads
100 redo size
379 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
1 rows processed

设置了query_rewrite_integrity=trusted,告诉oracle使用oralce强加的约束,
以及任意关系存在于数据中的而非数据库强加的关系可以重写查询,设置过后数据库
认为数据中有非数据库强加的emp和dept表之间的关系存在,则数据库认为可以采用
查询重写,使用物化视图。此时oracle对新插入的数据认为是违反了的emp和dept表之间
约束的关系,所以并没有对新插入的行的做记数,及时物化视图做刷新,也没有将新插入
的数据加到物化视图中去,oracle认识到我们告诉他的数据不可靠, 可以知道:
1、对于大型数据仓库可以非常相信物化视图,不必自己再做的量数据的校验;
2、如果你要你想要的数据,必须自己一确保数据的可靠,100%的净化了数据;

讲了半天才将自己讲懂。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: