物化查询表和视图(MQT & View)

  1. 物化查询表(MQT)相关

物化查询表(MQT)的定义是以一次查询的结果为基础的。MQT 可以显著提高查询的性能。本文将介绍 MQT、总结表(summary)和 staging 表,并通过一些实用的例子展示如何创建和使用物化查询表。

  1. 1概念与分类

    物化查询表(MQT:Materialized Query Tables)是一种以一次查询的结果为基础定义的表。包含在物化查询表中的数据来自定义物化查询表时所基于的一个或多个表。您可以将 MQT 看作一种物化的视图,视图和 MQT 都是基于一个查询来定义的。每当视图被引用时,视图所基于的查询便会运行。但是,MQT 实际上则是将查询结果保存为数据,您可以使用 MQT 中的这些数据,而不是使用底层表中的数据。

物化查询表可以显著提高查询的性能,尤其是提高复杂查询的性能。如果优化器确定查询或查询的一部分可以用一个 MQT 来解决,那么就会重写查询,以便利用 MQT。

MQT 可以在创建表时定义,或者定义为系统维护的 MQT,或者定义为用户维护的 MQT。下面的几个小节将介绍这两种类型的 MQT,另外再介绍总结表staging 表。后面的例子要求连接到 SAMPLE 数据库。如果您系统上还没有创建 SAMPLE 数据库,那么可以通过在命令行提示符下输入 db2sampl 命令来创建这个数据库。

1.1.1系统维护的MQT

       这种物化查询表中的数据是由系统维护的。当创建这种类型的 MQT 时,可以指定表数据是 REFRESH IMMEDIATE 还是 REFRESH DEFERRED。通过 REFRESH 关键字可以指定如何维护数据。DEFERRED 的意思是,表中的数据可以在任何时候通过 REFRESH TABLE 语句(refresh table TableName)来刷新。不管是 REFRESH DEFERRED 还是REFRESH IMMEDIATE 类型的系统维护的 MQT,对它们的 insert、update 或 delete 操作都是不允许的。但是,对于 REFRESH IMMEDIATE 类型的系统维护的 MQT,可以通过 对底层表的更改(即 insert、update 或 delete 操作)来更新。

如下展示了一个创建 REFRESH IMMEDIATE 类型的系统维护的 MQT 的例子。这个表名为 EMP,它基于 SAMPLE 数据库中的底层表 EMPLOYEE 和 DEPARTMENT。由于 REFRESH IMMEDIATE MQT 要求查询的 select 列表中引用的每个表中至少有一个惟一键,所以我们首先分别在 EMPLOYEE 表的 EMPNO 列上、DEPARTMENT 表的 DEPTNO 列上定义一个惟一性约束。DATA INITIALLY DEFERRED 子句的意思是,在执行 CREATE TABLE 语句的时候,并不将数据插入到表中。MQT 被创建好之后,就处于检查暂挂(check pending)状态,在对它执行 SET INTEGRITY 语句之前,不能查询它。IMMEDIATE CHECKED 子句规定,根据用于定义该 MQT 的查询对数据进行检查,并刷新数据。NOT INCREMENTAL 子句规定对整个表进行完整性检查。通过查询 EMP 物化查询表发现,它现在已经填入了数据。 脚本如下:

 

alter table employee add unique (empno);–定义一个惟一性约束

alter table department add unique (deptno) ;–定义一个惟一性约束

drop table emp ;

create table emp

             as (select e.empno, e.firstnme, e.lastname, e.phoneno, d.deptno,

                      substr(d.deptname, 1, 12) as department, d.mgrno

                 from employee e, department d

               where e.workdept = d.deptno

                 )

data initially deferred refresh immediate ;–此时表emp处于检查暂挂状态

set integrity for emp immediate checked not incremental ;

  如执行脚本:delete from emp where empno=’000010′ 会出现如下的错误:【SQL0150N  INSERT、DELETE、UPDATE 或 MERGE语句中的目标全查询、视图、类型表、具体查询表或分级表是不允许对其执行所请求的操作的目标。  SQLSTATE=42807】

1.1.2用户维护的 MQT

这种物化查询表中的数据是由用户维护的。只有 REFRESH DEFERRED 物化查询表可以定义为 MAINTAINED BY USER,不能对用户维护的 MQT 发出 REFRESH TABLE 语句,用户维护的 MQT 却 允许对它们执行 insert、update 或 delete 操作。

如下展示了一个创建 REFRESH DEFERRED 类型的用户维护的 MQT 的例子。这个表名为 ONTARIO_1995_SALES_TEAM,它基于数据库 SAMPLE 中的底层表 EMPLOYEE 和 SALES。同样,DATA INITIALLY DEFERRED 子句的意思是,在执行 CREATE TABLE 语句的时候,并不将数据插入到表中。MQT 被创建之后,便处于检查暂挂状态,在对它执行 SET INTEGRITY 语句之前,不能查询它。MATERIALIZED QUERY IMMEDIATE UNCHECKED 子句规定,该表将启用完整性检查,但是不必检查它是否违反了完整性约束,便可以使之脱离检查暂挂状态。 接下来,为了填充数据到 MQT 中,我们将导入从 EMPLOYEE 和 SALES 表中导出的数据。用于导出数据的查询与用于定义 MQT 的查询是一致的。然后,我们将插入另外一条记录到 ONTARIO_1995_SALES_TEAM 表中。

通过查询 ONTARIO_1995_SALES_TEAM 物化查询表发现,它现在已经填入了刚才导入的和插入的数据,这表明用户维护的 MQT 的确可以直接被修改。脚本如下:

 

drop table ontario_1995_sales_team;

create table ontario_1995_sales_team as 

      (select distinct e.empno, e.firstnme,

            e.lastname, e.workdept, e.phoneno, ‘Ontario’ as region,

            year(s.sales_date) as year

       from employee e, sales s

     where e.lastname = s.sales_person and year(s.sales_date) = 1995 AND left(s.region, 3) = ‘Ont’

        ) data initially deferred refresh deferred maintained by user ;

–启用完整性检查

set integrity for ontario_1995_sales_team materialized query immediate unchecked ;

–导出数据

export to c:\team.del of del

select distinct e.empno, e.firstnme, e.lastname, e.workdept, e.phoneno,

     ‘Ontario’ as region, year(s.sales_date) as year

from employee e, sales s

where e.lastname = s.sales_person and year(s.sales_date) = 1995 and left(s.region, 3) = ‘Ont’ ;

–导入数据

import from c:\team.del of del insert into ontario_1995_sales_team ;

–插入数据

insert into ontario_1995_sales_team values (‘006900’, ‘RUSS’, ‘DYERS’, ‘D44’, ‘1234’, ‘Ontario’, 1995) ;

1.1.3.总结表

总结表是一种特殊类型的 MQT,它们的 fullselect 包含一个 GROUP BY 子句,该子句总结 fullselect 中所引用表中的数据。如下展示了一个简单的创建总结表的例子。该表名为 SALES_SUMMARY,它基于 SAMPLE 数据库中的底层表 SALES。同样,DATA INITIALLY DEFERRED 子句的意思是,在执行 CREATE TABLE 语句的时候,并不将数据插入到表中。REFRESH DEFERRED 子句的意思是,在任何时候都可以用 REFRESH TABLE 语句刷新该表中的数据。当这个 MQT 刚创建且还没有发出 REFRESH TABLE 语句的时候,对它的查询将返回一个错误。而执行了 REFRESH TABLE 语句之后,对它的查询可以成功运行。

在对 SALES 表执行插入操作,再刷新总结表之后,对总结表的查询表明,对底层表的更改已经反映到总结表中:销售员 Lee 在 Ontario-South 地区的总销售量增加了 100。类似地,在对底层表执行 update 或 delete 操作之后,也可以在总结表中观察到相应的变化。脚本如下:

drop table sales_summary ;

create table sales_summary as

(select sales_person, region, sum(sales)as total_sales

 from sales

 group by sales_person, region

)data initially deferred refresh deferred ;

refresh table sales_summary ;–刷新之前不能进行查询操作。

–修改底层表(源表)

insert into sales values (’06/28/2005′, ‘LEE’, ‘Ontario-South’, 100);

refresh table sales_summary;–刷新

select * from sales_summary;–底层表的修改被反应到MQT表

     不能对其进行insert、delete、update等操作。

1.1.4 staging 表

如果 REFRESH DEFERRED MQT 有一个相关联的 staging 表,那么可以对其执行增量刷新。staging 表收集更改,以便应用这些更改,使得 MQT 与它的底层表同步。可以使用 CREATE TABLE 语句创建一个 staging 表。然后,当 MQT 的底层表被修改时,变化就会传播过来,并立即被添加到 staging 表中。其思想是,使用 staging 表增量式地刷新 MQT,而不是从头开始重新生成 MQT。增量式维护这种方式可以显著提高性能。当刷新操作完成时,staging 表就会被删除。staging 表被创建之后,便处于悬挂(不一致)状态。在开始收集底层表上的更改之前,它必须脱离这种状态。为此,可以使用 SET INTEGRITY 语句。

如下展示了一个使用有关联总结表的 staging 表的例子。总结表名为 EMP_SUMMARY,它基于 SAMPLE 数据库中的底层表 EMPLOYEE。DATA INITIALLY DEFERRED 子句的意思是,在执行 CREATE TABLE 语句的时候,并不将数据插入到表中。而 REFRESH DEFERRED 子句的意思是,在任何时候都可以使用 REFRESH TABLE 语句刷新该表中的数据。staging 表名为 EMP_SUMMARY_S,它与总结表 EMP_SUMMARY 相关联。PROPAGATE IMMEDIATE 子句规定,在 insert、update 或 delete 操作中对底层表做出的任何更改,都将被累积在 staging 表中。对于这两个表,都发出 SET INTEGRITY 语句,以便使它们都脱离悬挂状态。

不出所料,此时对总结表的查询没有返回任何数据。REFRESH TABLE 语句返回一条警告,提示说 “integrity of non-incremental data remains unverified”。这也不值得惊讶。再次查询总结表,仍然没有返回任何数据。但是,当我们插入新的一行数据到底层的 EMPLOYEE 表之后,再次查询 staging 表 EMP_SUMMARY_S 便返回一行记录,这行数据与刚才插入的数据是一致的。staging 表中有三个列与其底层总结表中的三列相同,另外还有两个由系统使用的列:GLOBALTRANSID(每个被传播的行对应的全局事务 ID)和 GLOBALTRANSTIME(事务的时间戳)。再次查询总结表,又是没有返回数据,但是当执行了 REFRESH TABLE 语句之后,查询得以成功运行。脚本如下:

 

create table emp_summary as

 (select workdept, job, count(*) as count

        from employee group by workdept, job

)data initially deferred refresh deferred ;–定义总结表emp_summary

create table emp_summary_s for emp_summary propagate immediate ; –定义staging表

set integrity for emp_summary materialized query immediate unchecked ;

set integrity for emp_summary_s staging immediate unchecked ;

select * from emp_summary;– 0 record(s) selected.

select * from emp_summary_s;– 0 record(s) selected.

refresh table emp_summary;

SQL1594W  Integrity of non-incremental data remains unverified by the

database manager.  SQLSTATE=01636

select * from emp_summary;– 0 record(s) selected.

select * from emp_summary_s;– 0 record(s) selected.

insert into employee

 values (‘006900’, ‘RUSS’, ‘L’, ‘DYERS’, ‘D44’, ‘1234’, ‘1960-05-05’,

 ‘FIELDREP’, 5, ‘M’, ‘1940-04-02’, 10000, 100, 1000);–底层表插入数据

select * from emp_summary;– 0 record(s) selected.

select * from emp_summary_s;– 1 record(s) selected.

refresh table emp_summary;

SQL1594W  Integrity of non-incremental data remains unverified by the database

manager.  SQLSTATE=01636

select * from emp_summary;– 1 record(s) selected.

    不能对staging表emp_summary_s进行refresh操作,如果在建好总结表emp_summary之后执行refresh操作,emp_summary中就填充了所有的数据,而emp_summary_s中则是存储底层表变化的数据。,如果删除了刚才在employee中插入的数据,在查询会多加一条记录。

 

   select * from emp_summary_s;–2 record(s) selected.

在 SYSCAT.TABDEP 系统编目视图中,对于一个物化查询表在其他对象上的每个依赖关系,都有相应的一行。您可以查询这个视图,获得对我们创建的 MQT的依赖关系的总结。MQT 有一个值为 ‘S’ 的 DTYPE。TABNAME 列列出 MQT 的名称,BNAME 列列出相应的 MQT 所依赖的数据库对象的名称。BTYPE 列显示对象类型:’T’ 表示表,’I’ 表示索引,’F’ 表示函数实例。

 

select substr(tabname,1,24) as tabname, dtype, substr(bname,1,24) as bname, btype
from syscat.tabdep where dtype = ‘S’ ;

参考:http://www.ibm.com/developerworks/cn/db2/library/techarticles/dm-0509melnyk/

2、视图

一般来说,数据存储在 DB2 中的关系表中。每个表由许多列和行组成。表列是在创建表期间定义的。还可以在创建表之后添加或删除它们。表中存储的数据需要与数据列定义保持一致。每个表可以有多个索引和视图。

  视图(view) 就像是一个逻辑表,它由一个 SELECT 语句从一个或多个表或视图获得的结果集组成。与关系表不同,视图中的数据不需要物理地存储在硬盘上。当查询视图时就会获取数据。除了在系统编目中存储它的定义之外,视图不使用物理空间。在创建视图之后,可以使用数据操纵语言(Data Manipulation Language,DML)查询视图,甚至更新视图。视图提供了灵活的数据访问功能,可以访问一个表的子集或者来自多个表的结果集的联结,同时隐藏了基表中数据的复杂性。

为了提供数据库对象(比如表、索引和视图)的逻辑视图,使用一个或多个模式对它们进行分类。模式(schema) 是数据库对象的一个逻辑分类。可以使用相同或不同的模式创建多个数据库对象。例如,在表空间 SYSCATSPACE 中,所有基本系统表和索引都分组在同一个模式 SYSIBM 中。基本编目表和索引的所有视图分组在模式 SYSCAT 或 SYSSTAT 中。创建视图的基本语法如下:

 

DROP VIEW ViewName ;  –删除视图

CREATE VIEW <ViewName>[(列名组)] AS <子查询> ; –删除视图

注:在创建视图时,并非所有的select子查询都可用,如:compute和compute by,order by[除非与top一起连用] 是不可以使用的,但对视图的查询不受限制。在视图创建时,必须为没有标题列指定标题(列名)。

在数据库DBTEST中做了如下测试,脚本如下:

 

DROP VIEW v_T1 ; –删除视图

CREATE VIEW v_T1 AS SELECT * FROM t1 ; –删除视图

SELECT * FROM v_T1 ;

DELETE FROM v_T1 WHERE id = 4;–对视图进行delete操作

INSERT INTO v_T1(Msg) values(‘view test of insert’); –对视图进行insert操作

UPDATE v_T1 SET Msg=’view test of update’ WHERE id=3 ; –对视图进行update操作

SELECT * FROM v_T1 ;

SELECT * FROM T1 ;

查询结果一致,如下:

 

1

记录1,离线备份

2

记录2,增量备份

3

view test of update

5

view test of insert

    由此可知,我们可以对视图进行delete、insert、update操作,对视图的修改也影响到源表的改动,上例中视图v_T1具有和表T1一致的数据,对视图修改后,视图v_T1和表T1的数据一致。

总的说来,视图(view)是从一个或几个基本表中根据用户需要而做成一个虚表,它在存储时只存储视图的定义,而没有存储对应的数据,视图只在刚刚打开的一瞬间,通过定义从基表中搜集数据,并展现给用户。
  视图与查询的区别:
  视图和查询都是用由sql语句组成,这是他们相同的地方,但是视图和查询有着本质区别:视图存储为数据库设计的一部分,而查询则不是,更新限制的要求不一样。
  要注意:因为视图来自于表,所以通过视图可以间接对表进行更新,我们也可以通过update语句对表进行更新,但是对视图和查询更新限制是不同的,以下我们会知道虽然通过视图可以间接更新表但是有很多限制.
  3:排序结果:通过sql语句,可以对一个表进行排序,而视图则不行。比如:

 

CREATE VIEW v_T1 AS SELECT * FROM t1 ORDER BY id DESC,会出现如下错误:

SQL20211N  规范 ORDER BY 或 FETCH FIRST n ROWS ONLY 无效。

视图的优点:
  1:能分割数据,简化观点。可以通过select和where来定义视图,从而可以分割数据基表中某些对于用户不关心的数据,使用户把注意力集中到所关心的数据列.进一步简化浏览数据工作;
  2:为数据提供一定的逻辑独立性。 如果为某一个基表定义一个视图,即使以后基本表的内容发生改变了也不会影响“视图定义”所得到的数据;
  3:提供自动的安全保护功能。 视图能像基本表一样授予或撤消访问许可权;
  4:视图可以间接对表进行更新,因此视图的更新就是表的更新;

视图的修改:
  格式:alter view 视图名 as 新的select语句
  修改视图和删除再重建视图都是执行新的select语句,所以差别并不大,为此要保存好之前的创建视图的脚本。
  如何通过视图修改基本表的数据.
  A:在视图上使用insert语句
  通过视图插入数据与直接在表中插入数据一样,但视图毕竟不是基本表.因此在进行数据插入时还是有一定的限制。
  1:如果视图上没有包括基本表中属性为not null[不能为空]的列,那么插入操作会因为那些列是null值而失败;
  2:如果某些列因为某些规则或约束的限制而不能直接接受从视图插入的列时,插入会失败;
  3:如果在视图中包含了使用统计函数的结果,或是包含计算列,则插入操作会失败;
  4:不能在使用了distinct语句的视图中插入值;
  5:不能在使用了group by语句的视图中插入值。

  B:使用update更新视图中的数据
  1:更新视图与更新表格一样,但是在视图中使用了多个基本表连接的情况下,每次更新操作只能更新来自基本表的一个数据列;
例如:创建以下视图:                              
create view del as                                 
select 职工号,姓名,部门名称,负责人 from work1,部门
where work1.部门编号=部门.部门编号                
  如果再执行下面的语句时:                      
update del set 职工号=’001′,部门名称=’wenda’       
where 职工号=’01′[出现错误]                       
  只能够改成:                                  
update del set 职工号=’001′ where 职工号=’01’      
update del set 部门名称=’wenda’ where 职工号=’01’   
  2:不能在使用了distinct语句的视图中更新值;
  3:不能在使用了group by语句的视图中更新值。

  C:使用delete删除视图中数据.
  通过视图删除数据最终体现为从基本表中删除数据
  格式:delete 视图名 [where 条件]
  说明:当视图由两个以上的基表构成时,不允许删除视图的数据

DB2对视图的规定:
     ⑴若视图是由两个以上基本表导出的,则此视图不允许更新
     ⑵若视图的字段来自字段表达式或常数,则不允许对此视图执行INSERT和UPDATE操作,但允许执行DELETE操作
     ⑶若视图的字段来自集函数,则此视图不允许更新
     ⑷若视图定义中含有GROUP BY子句,则此视图不允许更新
     ⑸若视图定义中含有DISTINCT短语,则此视图不允许更新
     ⑹若视图定义中有嵌套查询,并且内层查询的FROM子句中涉及的表也是导出该视图的基本表,则此视图不允许更新
     ⑺一个不允许更新的视图上定义的视图也不允许更新

 

 

    原文作者:颜朵A
    原文地址: https://blog.csdn.net/m0_37392721/article/details/81902587
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞