视图(View)是一个命名的虚表,它由一个查询来定义,可以当做表使用。与持久表(permanent table)不同的是,视图中的数据没有物理表现形式。

视图的作用

视图在数据库中发挥着重要的作用。视图的主要用途之一是被用做一个抽象装置,特别是对于一些应用程序,程序本身不需要关心基表(base table)的结构,只需要按照视图定义来获取数据或者更新数据,因此,视图同时在一定程度上起到一个安全层的作用。

MySQL从5.0版本开始支持视图,创建视图的语法如下:

CREATE

[OR REPLACE]

[ALGORITHM={UNDEFINED|MERGE|TEMPTABLE}]

[DEFINER={user|CURRENT_USER}]

[SQL SECURITY{DEFINER|INVOKER}]

VIEW view_name[(column_list)]

AS select_statement

[WITH[CASCADED|LOCAL]CHECK OPTION]

虽然视图是基于基表的一个虚拟表,但是我们可以对某些视图进行更新操作,其实就是通过视图的定义来更新基本表,我们称可以进行更新操作的视图为可更新视图(updatable view)。视图定义中的WITH CHECK OPTION就是指对于可更新的视图,更新的值是否需要检查。

我们先看个例子:

create table t(id int);

create view v_t as select * from t where t<10;

ERROR 1054(42S22):Unknown column't'in'where clause'

create view v_t as select * from t where id<10;

insert into v_t select 20;

select * from v_t;

我们创建了一个id<10的视图,但是往里插入了id为20的值,插入操作并没有报错,但是我们查询视图还是没有能查到数据。

接着我们更改一下视图的定义,加上WITH CHECK OPTION:

alter view v_t as select * from t where id<10 with check option;

insert into v_t select 20;

ERROR 1369(HY000):CHECK OPTION failed'mytest.v_t'

这次MySQL数据库会对更新视图插入的数据进行检查,对于不满足视图定义条件的,将会抛出一个异常,不允许数据的更新。

MysQL DBA一个常用的命令是show tables,会显示出当前数据库下的表,视图是虚表,同样被作为表而显示出来,

我们来看前面的例子:show tables;

show tables命令把表t和视图v_t都显示出来了。如果我们只想查看当前数据库下的基表,可以通过information_schema架构下的TABLE表来查询,并搜索表类型为BASE TABLE的表,如:

select * from information_schema.TABLES where table_type='BASE TABLE' and table_schema=database();

要想查看视图的一些元数据(meta data),可以访问information_schema架构下的VIEWS表,该表给出了视图的详细信息,包括视图定义者(definer)、定义内容、是否是可更新视图、字符集等。如我们查询VIEWS表,可得:

select * from information_schema.VIEWS where table_schema=database();

物化视图

Oracle数据库支持物化视图——该视图不是基于基表的虚表,而是根据基表实际存在的实表。物化视图可以用于预先计算并保存表连接或聚集等耗时较多的操作结果,这样,在执行复杂查询时,就可以避免进行这些耗时的操作,从而快速得到结果。物化视图的好处是,对于一些复杂的统计类查询能直接查出结果。在Microsoft SQL Server数据库中,称这种视图为索引视图。

在Oracle数据库中,物化视图的创建方式包括BUILD IMMEDIATE和BUILD DEFERRED这两种。BUILD IMMEDIATE是默认的创建方式,在创建物化视图的时候就生成数据,而BUILD DEFERRED则在创建时不生成数据,以后根据需要再生成数据。

查询重写是指当对物化视图的基表进行查询时,Oracle会自动判断能否通过查询物化视图来得到结果。如果可以,则避免了聚集或连接操作,而直接从已经计算好的物化视图中读取数据。

物化视图的刷新是指当基表发生了DML操作后,物化视图何时采用哪种方式和基表进行同步。

刷新的模式有两种:ON DEMAND和ON COMMIT。ON DEMAND指物化视图在用户需要的时候进行刷新,ON COMMIT指物化视图在对基表的DML操作提交的同时进行刷新。刷新的方法有四种:FAST、COMPLETE、FORCE和NEVER。FAST刷新采用增量刷新,只刷新自上次刷新以后进行的修改。COMPLETE刷新对整个物化视图进行完全的刷新。如果选择FORCE方式,则Oracle在刷新时会去判断是否可以进行快速刷新,如果可以则采用FAST方式,否则采用COMPLETE的方式。NEVER指物化视图不进行任何刷新。

MySQL数据库本身并不支持物化视图,换句话说,MySQL数据库中的视图总是虚拟的,但是我们可以通过一些机制来实现物化视图的功能。

要创建一个ON DEMAND的物化视图还是比较简单的,我们可以定时把数据导入另一张表。例如,我们有如下的订单表,记录了用户采购电脑设备:

create table Orders(

  order_id INT UNSIGNED NOT NULL AUTO_INCREMENT,

  product_name VARCHAR(30) NOT NULL,

  price DECIMAL(8,2) NOT NULL,

  amount SMALLINT NOT NULL,

  primary key(order_id)

)ENGINE=InnoDB;

INSERT INTO Orders VALUES

  (NULL,'CPU',135.5,1),

  (NULL,'Memory',48.2,3),

  (NULL,'CPU',125.6,3),

  (NULL,'CPU',105.3,4);

select * from Orders\G;

接着我们建立一张物化视图,用来统计每件物品的信息,如:

CREATE TABLE Orders_MV(

  product_name VARCHAR(30) NOT NULL,

  price_sum DECIMAL(8,2) NOT NULL,

  amount_sum INT NOT NULL,

  price_avg FLOAT NOT NULL,

  orders_cnt INT NOT NULL,

  UNIQUE INDEX(product_name)

);

INSERT INTO Orders_MV

  SELECT product_name,

  SUM(price),SUM(amount),AVG(price)

  COUNT(*)

  FROM Orders

  GROUP BY product_name;

select * from Orders_MV;

这里我们把物化视图定义为一张表,只不过表名以_MV结尾,让DBA能很好地理解这张表的作用。这样就有了一个统计信息,如果是要实现ON DEMAND的物化视图,只需把表清空,重新导入数据即可。当然,这是完全(Complete)刷新方式。要实现快(Fast)刷新方式,其实也是可以的,只不过稍微复杂点,需要记录上次统计时的order_id的位置。

但是如果要实现On Commit的物化视图,这就不是如上面这么简单了。Oracle数据库中通过物化视图日志来实现,很显然MySQL数据库没有这个日志,但是通过触发器,我们同样可以达到这个目的:

DELIMITER$$

CREATE TRIGGER tgr_Orders_insert

AFTER INSERT ON Orders

FOR EACH ROW

BEGIN

  SET@old_price_sum=0;

  SET@old_amount_sum=0;

  SET@old_price_avg=0;

  SET@old_orders_cnt=0;

  SELECT IFNULL(price_sum,0),IFNULL(amount_sum,0),IFNULL(price_avg,0),IFNULL(orders_cnt,0)

  FROM Orders_MV

  WHERE product_name=NEW.product_name

  INTO @old_price_sum,@old_amount_sum,@old_price_avg,@old_orders_cnt;

  SET@new_price_sum=@old_price_sum+NEW.price;

  SET@new_amount_sum=@old_amount_sum+NEW.amount;

  SET@new_orders_cnt=@old_orders_cnt+1;

  SET@new_price_avg=@new_price_sum/@new_orders_cnt;

  REPLACE INTO Orders_MV

  VALUES(NEW.product_name,@new_price_sum,@new_amount_sum,@new_price_avg,@new_orders_cnt);

END;

$$

DELIMITER;

insert into Orders values(NULL,'SSD',299,3);

insert into Orders values(NULL,'Memory',47.9,5);

select * from Orders_MV;

这里对表Orders添加了一个INSERT的触发器,每次Insert操作都会重新统计Orders_MV中的数据,这样就实现了ON_Commit的物化视图功能。但是Orders表可能还会有Update和Delete的操作,所以应该还需要实现Delete和Update的触发器。

通过触发器我们实现了物化视图的功能,但是MySQL本身并不支持物化视图,因此对于物化视图支持的查询重写(Query Rewrite)功能就显得无能为力了。

InnoDB的视图的更多相关文章

  1. mysql之show engine innodb status解读

    注:以下内容为根据<高性能mysql第三版>和<mysql技术内幕innodb存储引擎>的innodb status部分的个人理解,如果有错误,还望指正!!   innodb存 ...

  2. show engine innodb status 详解

    找个mysql客户端,执行show engine innodb status得到如下结果: 详细信息如下: ************************************** ======= ...

  3. show engine innodb status解读

    xiaoboluo768   注:以下内容为根据<高性能mysql第三版>和<mysql技术内幕innodb存储引擎>的innodb status部分的个人理解,如果有错误,还 ...

  4. mysql之show engine innodb status解读(转)

    add by zhj: 我第一次知道这个命令是线上服务出了问题,然后同事用这个命令去查看死锁.但用这个命令看死锁有一定的局限性,它只能看到最后一次死锁, 而且只能看到死锁环中的两个事务所执行的最后一条 ...

  5. 0804SHOW ENGINE INNODB STATUS

    转自http://blog.csdn.net/github_26672553/article/details/52931263 innodb存储引擎在show engine innodb status ...

  6. 0719show engine innodb status解读

    转自 http://www.cnblogs.com/zengkefu/p/5678100.html 注:以下内容为根据<高性能mysql第三版>和<mysql技术内幕innodb存储 ...

  7. MySQL数据库和InnoDB存储引擎文件

    参数文件 当MySQL示例启动时,数据库会先去读一个配置参数文件,用来寻找数据库的各种文件所在位置以及指定某些初始化参数,这些参数通常定义了某种内存结构有多大等.在默认情况下,MySQL实例会按照一定 ...

  8. Mysql - 触发器/视图

    触发器在之前的项目中, 应用的着实不多, 没有办法的时候, 才会去用这个. 因为这个东西在后期并不怎么好维护, 也容易造成紊乱. 我最近的项目中, 由于数据库设计(别人设计的)原因, 导致一些最简单功 ...

  9. [MySQL Reference Manual]14 InnoDB存储引擎

    14 InnoDB存储引擎 14 InnoDB存储引擎 14.1 InnoDB说明 14.1.1 InnoDB作为默认存储引擎 14.1.1.1 存储引擎的趋势 14.1.1.2 InnoDB变成默认 ...

随机推荐

  1. Android-有序广播

    在之前的博客,Android-广播概念,中介绍了(广播和广播接收者)可以组件与组件之间进行通讯,有两种类型的广播(无序广播 和 有序广播),这篇博客就来讲解有序广播的代码实现: 有序广播:接收者 可以 ...

  2. nginx 配置中的if判断

    正则表达式匹配:     ==:等值比较;     ~:与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写:     ~*:与指定正则表达式模式匹配时返回“真”,判断匹配与否时不区分字 ...

  3. nginx docker 方式启动后日志切分的正确姿势

    Linux系统的日志文件的切分主要是由logrotate来完成的,以centos7为例配置通常在/etc/logrotate.d 目录下 添加 nginx 文件 cat nginx /var/log/ ...

  4. IPA文件的自动化生成和无线分发

    1. IPA的无线分发 iOS应用开发测试过程中,通过无线网络进行IPA包的分发将是非常便捷的,于是也就有了类似testflightapp之类的平台.对于这一功能,我们也可以自己实现,只需要一个简单的 ...

  5. Tempdb--查看tempdb使用的脚本

    GO /****** Object: StoredProcedure [dbo].[usp_GetTempDBUsedSpace] Script Date: 03/05/2014 13:24:42 * ...

  6. VUE 学习笔记 三 模板语法

    1.插值 a.文本 数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值 <span>Message: {{ msg }}</span> v-once ...

  7. java环境和Tomcat环境

    这些变量名是一样的,变量的值需要自己根据自己的安装位置来确定 JAVA_HOME C:\Program Files\Java\jdk1.8.0_151 CATALINA_HOME(这个可能不需要) D ...

  8. 10-12Linux流编程的一些知识点

    第五章  Linux 的流编程 Linux流操作基础      流和文件的关系:流相当于一个缓冲区,可以将文件描述符和流关联,获得相应的缓冲区,以此来提高系统对磁盘的存取速度.     流的结构和操作 ...

  9. 一起学习《C#高级编程》1--类型的安全性

    感觉写随笔第一天就遇到了困难,感觉好费时间啊,回宿舍就得8点多,然后只能看一点书.之后写随笔,首先得回忆,然后组织,最后打字.还有就是宿舍迎来的断网的日子,特别不方便,只能第二天去公司发.本人目前是. ...

  10. Media change : please insert the disk labeled

    在Debian中使用apt-get安装软件包时经常会提示让你插入netinst的光盘: Media change: please insert the disc labeled 当没有时就无法进行安装 ...