视图
- 最近遇到mysql锁相关问题,在查阅资料时候,经常能看到在锁的解释中总有视图的概念出现,因此我觉得有必要先去了解一下视图相关的详细信息,有助于我对mysql锁相关的理解。
- 视图(View)是一个命名的虚拟表,由一个查询来定义,可以当成表使用。与持久表(permanent table)不同的是,视图中的数据没有物理表现形式(没有存储在文件)
视图的作用
-
视图在我们实际应用开发时候接触的比较少,但是他在数据库中扮演着重要的角色。视图的主要用途之一就是被用做一个抽象的装置,特别是对于某些场景下应用程序,程序不需要关心基础表(base table)的结构,只需要按照视图定义来获取数据,或者更新数据。因此视图同时在一定程度上起到一个安全层的作用。
-
mySql 的5.0 版本后才支持视图,预发格式如下:
CREATE VIEW <视图名> AS <SELECT语句>
-
视图名:指定视图的名称,名称在数据库中必须是唯一的,不能与其他表或者视图同名
-
select 语句:指定创建视图的select语句,可以用于查询多个基础表的源视图。
-
视图是基于表的一个虚拟表,但是我们可以对某些视图进行更新操作,其实就是通过视图定义来更新基本表,这种可以进行更新操作的视图是可更新视图(updatable view)。视图中定义的WITH CHECK OPTION 就是针对可更新视图做的设置。看如下案例:
create table t(id int);create view v_t as select * from t where id<10;insert into v_t select 20;select * from v_t;insert into v_t VALUES (9);select * from v_tselect * from t
- 创建一个id< 10的视图,但是往里插入了id为20的值,插入操作并没有报错,但是我们查询视图还是没有能查到的数据。但是我们在t中是可以看到有两天数据进行了insert, 我们可以修改一下视图的定义,加上WITH CHECH OPTION:
alter view v_t as select * from t where id < 10 with check option;insert into v_t select 30;
- 本次mysql数据操作后得到错误信息i:
[SQL]
insert into v_t select 30[Err] 1369 - CHECK OPTION failed 'test.v_t'
-
在添加with check option后mySql数据库会对更新视图插入的数据进行检查,对于不满足视图定义的条件的数据,抛出异常,不允许更新
-
mySql常用命令show tables, 会展示当前数据库下的表,视图是虚表,同样会被查询出。
-
mysql中有对应的语法用来查询基础表,排除视图:
select * from information_schema.TABLES where TABLE_TYPE = 'BASE TABLE' and TABLE_SCHEMA = DATABASE();
- 单独查询视图内容:
select * from information_schema.VIEWS where TABLE_SCHEMA = DATABASE();
物化视图
-
Oracle数据库才支持物化视图----该视图不是基于基表的虚表,而是根据基表实际存在的实体表。可以用于预先计算并保存表的其他纬度信息,这样在执行复杂查询时候,可以避免进行耗时的一些操作,快速得到结果
-
物化视图需要解决的一个问题在于当基础表发送DML操作后,物化视图必须跟进,刷新模式有两种:
- ON DEMAND :物化视图在用户使用时候进行刷新
- ON COMMIT:在对基础表DML操作提交同时进行刷新
-
刷新方法有四种:
- FAST:增量刷新,只刷新上次刷新以后进行的修改
- COMPLETE:对整个物化视图进行全量的刷新
- FORCE:刷新时候回判断是否可以进行快速刷新,如果可以就采用FAST,否则用COMPLETE
- NEVER:不进行任何刷新
-
以上物化视图都是Oracle数据库才支持,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=INNODBinsert into orders values
(null, 'cpu', 138.2,1),
(null, 'memory', 89.2,5),
(null, 'cpu', 98.2,6),
(null, 'cpu', 333.2,33);select * from orderscreate 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
-
orders 数据:
-
orders_mv 数据
-
如上方式我们吧物化视图定义为一张表,不过我们以mv结尾,让DBA很好的理解这张表的作用,这样就有了一个统计信息,如果是要实现ON DEMAND的物化视图,只需要吧表清空,重新导入即可。这种方式是Complete刷新方式
-
FAST刷新方式也是可以的,每次刷新纪录上次order_id的位置,下次更新之后的数据。
-
ON COMMIT方式的话就不容易了,Oracle数据库中通过物化视图日志来实现的,mySQL没有这个功能,mySQL需要实现的话可以通过触发器实现。(略)
上一篇:数据结构与索引-- mySql索引诡异事件
下一篇:mysql技术分享–表分区实现