MySQL还能这样玩---第五篇之视图应该这样玩

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL还能这样玩---第五篇之视图应该这样玩相关的知识,希望对你有一定的参考价值。

mysql还能这样玩---第五篇之视图应该这样玩


什么是视图

视图相对于普通表而言,有下面这些优势:

  • 简单 : 使用视图的用户完全不需要关系后面对于的表的结构,关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集
  • 安全 : 使用视图的用户只能访问他们可以查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图可以简单实现
  • 数据独立: 一旦视图的结果确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。

临时表原理

什么是临时表:MySQL用于存储一些中间结果集的表,临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。为什么会产生临时表:一般是由于复杂的SQL导致临时表被大量创建

临时表分为两种,一种是内存临时表,一种是磁盘临时表。内存临时表采用的是memory存储引擎,磁盘临时表采用的是myisam存储引擎(磁盘临时表也可以使用innodb存储引擎,通过internal_tmp_disk_storage_engine参数来控制使用哪种存储引擎,从mysql5.7.6之后默认为innodb存储引擎,之前版本默认为myisam存储引擎)。分别通过Created_tmp_disk_tables 和 Created_tmp_tables 两个参数来查看产生了多少磁盘临时表和所有产生的临时表(内存和磁盘)。

内存临时表空间的大小由两个参数控制:tmp_table_size 和 max_heap_table_size 。一般来说是通过两个参数中较小的数来控制内存临时表空间的最大值,而对于开始在内存中创建的临时表,后来由于数据太大转移到磁盘上的临时表,只由max_heap_table_size参数控制。针对直接在磁盘上产生的临时表,没有大小控制。

下列操作会使用到临时表:

  • union查询
  • 对于视图的操作,比如使用一些TEMPTABLE算法、union或aggregation
  • 子查询
  • join 包括not in、exist等
  • 查询产生的派生表
  • 复杂的group by 和 order by
  • Insert select 同一个表,mysql会产生一个临时表缓存select的行
  • 多个表更新
  • GROUP_CONCAT() 或者 COUNT(DISTINCT) 语句

Mysql还会阻止内存表空间的使用,直接使用磁盘临时表:

  • 表中含有BLOB或者TEXT列
  • 使用union或者union all时,select子句有大于512字节的列
  • Show columns或者 desc 表的时候,有LOB或者TEXT
  • GROUP BY 或者 DISTINCT 子句中包含长度大于512字节的列

视图原理





总结:在定义视图的时候,尽可能不要让其走临时表算法,而选择合并算法


视图的CRUD

创建视图

create view 视图名
as 
查询语句;

或者

create or replace 视图名
as
查询语句;

使用视图

select v.wID from v;

修改视图

create or replace 视图名
as
查询语句;

或者

alter view 视图名
as
查询语句;

更新视图注意事项

视图的可更新性和查询的定义有关系,以下类型的视图是不可更新的

  • 包含以下关键字的SQL语句: 聚合函数(SUM,MIN,MAX,COUNT等),DISTINCT。GROUP BY , HAVING,UNION或者UNION ALL
  • 常量视图
  • SELECT中包含子查询
  • JOIN
  • FROM一个不能更新的视图
  • WEHERE子句的子查询引用了FROM子句中的表

为什么上面的视图都是不可更新的呢? 看底层实现

重点在于使用临时表算法实现的视图是不可以被更新的,在原表和视图无法建立一一映射的条件下,就会使用临时表算法


举例: 以下视图都是不可更新的

包含聚合函数:
create or replace view pay_sum as
select staff_id,sum(amount) from payment group by staff_id;
常量视图:
create or replace view pi as 
select 3.14 as pi
select中包含子查询:
create view city_view as 
select (select city from city where city_id=1);

WITH [CASCADED | LOCAL ] CHECK OPTION决定了是否可以更新记录使其不再满足视图的条件,这个选项与ORACLE数据库中的选项是类似的:

  • LOCAL只要满足本视图的条件就可以更新
  • CASCADED则必须满足所有针对该视图的所有视图的条件才可以更新

没有明确LOCAL 和 CASCADED 的前提下,默认为CASCADED

举例: 对payment创建两层视图,并进行更新操作

create view payment_view as 
select payment_id,amount from payment
where amount < 10 
with check option
create view payment_view1 as 
select payment_id,amount from payment_view
where amount > 5 
with local check option
create view payment_view2 as 
select payment_id,amount from payment
where amount > 5
with cascaded check option

尝试更新:

成功:
update payment_view1 set amount=10
where payment_id=3;
失败:
update payment_view2 set amount=10
where payment_id=3;

payment_view1是WITH LOCAL CHECK OPTION的,所以只要满足本视图的条件就可以更新,但是payment_view2是WITH CASCADED CHECK OPTION的,必须满足针对该视图的所有视图才可以更新,因为更新后记录不再满足payment_view 的条件,所以更新操作提示错误退出。


删除视图

前提拥有删除该视图的DROP权限

drop view v1,v2,v3...

查看视图

show tables命令从mysql 5.1开始,会显示表和视图,不存在单独的show views命令

显示视图信息
show table status from 数据库名 like 表名/视图名
查看视图定义信息
show create view 

通过information_schema.views也可以查看视图的相关信息


视图对性能的影响


注意:是在使用临时表算法构建的视图中,无法使用索引,无法使用外层where条件在存储引擎层过滤掉不需要的行数


以上是关于MySQL还能这样玩---第五篇之视图应该这样玩的主要内容,如果未能解决你的问题,请参考以下文章

MySQL还能这样玩---第二篇之不为人知的分区

MySQL还能这样玩---第三篇之索引也可以如此easy

DWR第五篇之文件上传

javaWeb核心技术第五篇之jQuery

混合编程jni 第五篇之C++ 访问 Java代码

MySql-第五篇视图