MySQL 视图(View)原理解析


Posted in MySQL onMay 19, 2021

MySQL 5.0以后引入了视图。视图实际是一个自身不存储数据的虚拟数据表。实际这个虚拟表的数据来自于访问视图的 SQL 查询的结果。MySQL 处理视图和处理数据表差不多,通过这种方式来满足很多需求。视图和数据表在 MySQL 中共享命名空间,然而 ,MySQL 处理而二者的方式并不相同,例如,视图没有触发器,并且无法使用 DROP TABLE 移除视图。

下面以 world 样例数据库为例来展示视图的工作机制。

CREATE VIEW Oceania AS
	SELECT * FROM Country WHERE Continent = 'Oceania'
  WITH CHECK OPTION;

实现视图最简单的方式是执行SELECT查询语句并将结果放入到一张临时表中。之后,就可以在视图出现的地方引用这张临时表。例如下面的查询语句:

SELECT Code, Name FROM Oceania WHERE Name = 'Australia';

下面是服务端执行上面语句可能的形式(临时表名称是随意取的,实际内部不知道是什么):

CREATE TEMPORARY TABLE TMP_Oceania_123 AS 
	SELECT * FROM Country WHERE Continent = 'Oceania';
SELECT Code, Name FROM TMP_Oceania_123 WHERE NAME = 'Australia';

这种形式显然存在性能问题,最好的方式是将视图和查询的分布查询改为一句 SQL 语句,如下所示:

SELECT Code, Name FROM Country
WHERE Continent = 'Oceania' AND Name = 'Australia';

在 MySQL 中会使用两种算法,称之为 MERGE 和 TEMTABLE,而且会尽可能地使用 MERGE 算法。甚至,MySQL 能够将嵌套视图进行合并。下图是两种算法的区别:

MySQL 视图(View)原理解析

当视图中有 GROUP BY,DISTINCT,聚集函数,UNION,子查询或其他数据表之间不是一对一的关系时,MySQL 会使用 TEMPTABLE算法。如果想知道视图是使用 MERGE 还是 TEMPTABLE,可以使用 EXPLAIN 指令检查:

EXPLAIN SELECT * FROM <视图名称>;

如果在 select_type 中有 DERIVED 的话,则表示使用了 TEMPTABLE 算法。因此,如果隐藏的衍生表需要很高的代价产生,EXPLAIN 就会变得性能很低并且执行起来很慢,这是因为它需要实际执行和构建衍生表。这个算法是视图的属性而不会受到查询类型的影响。例如,假设创建视图的时候指定了算法,那么以后针对这个视图的查询都不会更改算法,即便有优化的空间:

CREATE ALGORITHM=TEMPTABLE VIEW v1 AS
SELECT * FROM Country;

可更新视图

可更新视图可以通过视图更新隐藏的基础表,只要指定的条件保持,就可以使用 UPDATE,DELETE 甚至是 INSERT 操作,就像操作普通表一样,例如下面的操作是有效的:

UPDATE Oceania SET Population = Population * 1.1 WHERE NAME = 'Australia';

如果视图包括 GROUP BY,UNION,聚合函数或其他的一些概念,那么该视图就不可更新。所有使用了 TEMPTABLE 算法的视图都不可以更新。

CHECK OPTION 子句用于保证任何通过视图更改的数据行在更改后需要保持与视图的 WHERE条件匹配。例如上面的例子,如果插入了一条 Continent 值不同的行,服务端就会报错。

视图的性能

很多人不会考虑使用视图提升性能,但是在某些情况下视图是可以提高性能的。而且还可以用视图去提升其他方面的性能,例如,在表结构重构时,被修改的数据表的视图不经修改也可以使用。还可以使用视图实现字段权限控制而不增加创建列权限的负荷:

CREATE VIEW public.employeeinfo AS
	SELECT firstname, lastname  --不包含身份证号
  FROM private.employeeinfo;
GRANT SELECT ON public.* to public_user;

使用 TEMPTABLE 算法的视图性能可能很糟糕(虽然也有可能比等效的 SQL 查询性能高)。这种视图可优化的空间不高。

视图可能让开发者误以为视图很简单,而事实上视图非常复杂。如果开发者不懂的试图的复杂性,那么就不会注意到视图与普通表查询之间的差别。如果使用EXPLAIN 指令的话有时候会发现产生上百行的分析结果输出,这是因为实际看起来是数据表的查询实际是视图,而视图可能引用其他数据表甚至是其他视图。

在使用视图改进性能时,需要仔细分析和测试。即便是 MERGE 算法的视图也会增加额外的负担,而且很难预测对性能的影响。视图实际在 MySQL 中使用了另外的优化途径。在高并发场景,视图可能导致查询优化器耗费大量时间在做计划和统计,甚至导致服务端卡顿。这个时候需要使用普通的 SQL 来替代视图。

视图的限制

MySQL 不像其他数据库服务器那样支持物理视图(物理视图即产生并将结果存在一个不可见的数据表中,并周期性地更新以从源数据刷新视图)。MySQL 也不支持视图的索引。MySQL 也不会保留视图的原始 SQL,如果我们视图通过执行 SHOW CREATE VIEW 指令去编辑视图,并且更改返回结果 SQL,会发现结果很奇特。查询SQL会按规范展开,并且使用内部的格式包裹,且没有格式化、注释和缩进。

以上就是MySQL 视图(View)原理解析的详细内容,更多关于MySQL 视图(View)原理的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
MySQL Shell的介绍以及安装
Apr 24 MySQL
仅用一句SQL更新整张表的涨跌幅、涨跌率的解决方案
May 06 MySQL
MySQL主从搭建(多主一从)的实现思路与步骤
May 13 MySQL
超详细教你怎么升级Mysql的版本
May 19 MySQL
mysql在项目中怎么选事务隔离级别
May 25 MySQL
基于MySql验证的vsftpd虚拟用户
Nov 07 MySQL
一文弄懂MySQL索引创建原则
Feb 28 MySQL
MySQL慢查询优化解决问题
Mar 17 MySQL
优化Mysql查询的示例
Apr 26 MySQL
MySQL数据库 安全管理
May 06 MySQL
MySQL常用慢查询分析工具详解
Aug 14 MySQL
详解MySQL的内连接和外连接
May 08 MySQL
超详细教你怎么升级Mysql的版本
详解mysql三值逻辑与NULL
MySQL时间盲注的五种延时方法实现
分析MySQL抛出异常的几种常见解决方式
详解MySQL数据库千万级数据查询和存储
May 18 #MySQL
详解MySQL连接挂死的原因
详解Mysql和Oracle之间的误区
May 18 #MySQL
You might like
PHP文件打开、关闭、写入的判断与执行代码
2011/05/24 PHP
PHP+Ajax异步带进度条上传文件实例
2016/11/01 PHP
CI框架入门之MVC简单示例
2016/11/21 PHP
js 实现复制到粘贴板的功能代码
2010/05/13 Javascript
简单的两种Extjs formpanel加载数据的方式
2013/11/09 Javascript
Javascript和Java获取各种form表单信息的简单实例
2014/02/14 Javascript
Node.js 的异步 IO 性能探讨
2014/10/08 Javascript
javascript之Array 数组对象详解
2016/06/07 Javascript
Bootstrap栅格系统使用方法及页面调整变形的解决方法
2017/03/10 Javascript
AngularJS自定义指令详解(有分页插件代码)
2017/06/12 Javascript
vue.js模仿京东省市区三级联动的选择组件实例代码
2017/11/22 Javascript
ES10的13个新特性示例(小结)
2019/09/23 Javascript
layui表格设计以及数据初始化详解
2019/10/26 Javascript
Vue状态模式实现窗口停靠功能(灵动、自由, 管理后台Admin界面)
2020/03/06 Javascript
详解Vue.js3.0 组件是如何渲染为DOM的
2020/11/10 Javascript
基于p5.js 2D图像接口的扩展(交互实现)
2020/11/30 Javascript
Python的Flask框架中@app.route的用法教程
2015/03/31 Python
Python中常用信号signal类型实例
2018/01/25 Python
Django之Mode的外键自关联和引用未定义的Model方法
2018/12/15 Python
使用Python进行体育竞技分析(预测球队成绩)
2019/05/16 Python
python实现爬取百度图片的方法示例
2019/07/06 Python
Flask框架学习笔记之使用Flask实现表单开发详解
2019/08/12 Python
pandas将多个dataframe以多个sheet的形式保存到一个excel文件中
2019/10/10 Python
canvas实现高阶贝塞尔曲线(N阶贝塞尔曲线生成器)
2018/01/10 HTML / CSS
JD Sports德国官网:英国领先的运动鞋和运动服饰零售商
2018/02/26 全球购物
澳大利亚领先的皮肤诊所:Skin Matrix(抗衰老、痤疮专家、药妆护肤)
2018/05/20 全球购物
汇科协同Java笔试题
2012/03/31 面试题
资深财务管理人员自我评价
2013/09/22 职场文书
高中生物教学反思
2014/02/05 职场文书
经典团队口号大全
2014/06/21 职场文书
团日活动总结怎么写
2014/06/25 职场文书
甲乙双方合作协议书
2014/10/13 职场文书
优秀团员个人总结
2015/02/26 职场文书
护士自荐信怎么写
2015/03/06 职场文书
五年级作文之成长
2019/09/16 职场文书
详解MySQL中的pid与socket
2021/06/15 MySQL