Mysql视图的做用及其性能分析

定义:视图是从一个或几个基本表导出的表,它与基本表不一样,是一个虚表。mysql

做用:算法

  1.简化操做,不用进行多表查询。sql

  2.当不一样种类的用用户共享同一个数据库时,很是灵活,(用户以不一样的数据库

方式看待同一数据. 安全

  3.视图对重构数据库提供了必定程度的逻辑独立性。函数

 数据的逻辑独立性是指:如增长新的关系或对原有的关系增长新的性能

字段,用户的应用程序不受影响.优化

 例如:原有一个Student(Sno,Sname,Ssex,Sage,Sdept)这样一个表.ui

     后来变更为:Sx(Sno,Sname,Sage)和SY(Sno,Ssex,Sdept)spa

两个表。

    这时候原表Student为SX和SY表天然链接的结果。

那么若是咱们一开始创建了一个试图:

 create view Student(Sno,Sname,Ssex,Sage,Sdept)

as  select SX.Sno,SX.Sname,SY.Ssex,SX,Sage,SY,Sdept

from SX,SY  where SX.Sno=SY.Sno;

 尽管数据库的逻辑结构改变了,可是应用程序没必要修改(由于这个这个

视图所定义的关系没有变啊)。 

【注意:试图只能在必定程度上提供数据的逻辑独立,好比因为

视图的更新是有条件的,所以应用程序中修改数据的语句可能仍会

由于基本表构造的改变而改变.

 4. 视图可以对机密数据提供安全保护 

   有了视图机制,就能够在设计数据库应用系统时,对不一样的用户定义不一样的视图,使机密数据不出如今不该该看到这些数据 的用户视图上。这样视图机制就自动提供了对机密数据的安全保护功能。例如,Student表涉及全校15个院系学生数据,能够在其上定义15个视图,每一个视图只包含一个院系的学生数据,并只容许每一个院系的主任查询和修改本原系学生视图。

  五、适当的利用视图能够更清晰地表达查询

    例如常常须要执行这样的查询“对每一个学生找出他得到最高成绩的课程号”。能够先定义一个视图,求出每一个同窗得到的最高成绩:
CREATE VIEW VMGRADE
AS
SELECT Sno,MAX(Grade) Mgrade
FROM SC
GROUP BY Sno;
而后用以下的查询语句完成查询:

SELECT SC.Sno,Cno FROM SC,VMGRADE WHERE SC.Sno = VMGRADE.Sno AND SC.Grade = VMGRADE.Mgrade;

 MySql视图的算法及其性能分析:

        mysql在处理视图时有两种算法,分别称为merge和temptable。

在执行“create view”语句时能够指定使用哪一种算法,所谓merge是指在

处理涉及到视图的操做时,将对视图的操做根据视图的定义进行展开,有点相似于

c语言中的宏展开. 

   例如设有如下表: 

  CREATE TABLE `comment` (
  `id` int(11) NOT NULL,
  `user_id` int(11) default NULL,
  `content` varchar(255) default NULL,
  PRIMARY KEY  (`id`),
  KEY `idx_comment_uid` (`user_id`)
) ENGINE=InnoDB;
假设user_id < 10000的用户为VIP用户,咱们能够这样建立一个视图来表示VIP用户的评论:
CREATE VIEW vip_comment AS SELECT * FROM comment WHERE user_id < 10000;
这时咱们在操做vip_comment视图时使用的就是MERGE算法

【通常在可以使用merge算法的时候mysql处理视图上没什么性能问题,

但并不是在任什么时候候都能使用merge算法.事实上,只要视图的定义稍稍有点复杂,mysql就没办法使用merge算法了.准确的说,只要视图定义中

使用了一下sql构造块就没法使用merge算法:

   (1)汇集函数(2)distinct (3)group by (4)having 

(5)having (6)集合操做(在mysql只有union,union all,没有except和intersect)(7)子查询.】


 

确实,在视图定义比较复杂的状况下,要对视图操做进行有效的优化是很是困难的。所以在这个时候,MySQL使用了一种以不变应万变的方法,即先执行视图定义,将其结果使用临时表保存起来,这样后续对视图的操做就转化为对临时表的操做。不能不说从单从软件设计的角度看,这样的方法很是的优雅,然而从性能角度,这一方法也是很是的差。

 

         好比咱们但愿使用以下的视图来表示每一个用户的评论数,即:

      CREATE VIEW comment_count AS SELECT user_id, count(*) AS count FROM comment GROUP           BY user_id;

       使用这个视图的时候,咱们可能内心有个小算盘。目前咱们先用这个视图顶着,若是性能确实有问题,那咱们就        再来搞一张comment_count的表,其中就记下来每一个用户的评论数。而咱们如今先用这个视图是为了未来要          是改的话会方便点(这也是视图--即教科书中所谓的外模式--这个东西存在的主要缘由之一,另外一主要缘由是          便于权限控制)。可是遇到了MySQL这个蠢货,咱们的算盘铁定会失败。

       咱们来看一下指定user_id从comment_count选取记录时的执行策略:

       mysql> explain select count(*) from comment_count where user_id = 90;

  能够看出,mysql首先是先执行comment_count的视图定义,

将结果存储在临时表中,选择出知足"user_id=90”的那一条

记录,这样,虽然咱们最终只须要统计90号用户的评论数,而且comment

表的user_id字段也有索引,mysql也会扫描整个comment表,并按

user_id分组计算出全部用户的评论数。

【这里面要注意的是即便在进行explain时,系统的物化也是要先执行的,

所以若评论不少的话explain也是同样的慢。这个问题的根源是

mysql的查询优化原本就存在不少问题.对于上述的查询,要达到比较

好的优化效果在数据库中通常是以下处理的:

1.将视图的操做转化为from字句中的子查询. 

select * from (select user_id,count(*) as count from comment

group by user_id)as comment_count where user_id=90;

2.子查询提高。由于子查询中使用了group by,所以先将外面的条件

做为提高后的having条件

select user_id,count(*) as count from comment group by usr_id

having user_id=90;

3.因为having条件中不涉及汇集函数,转化为where条件

select user_id ,count(*) as count from comment where user_id=90

group by user_id;

4.因为指定where条件后,user_id已是一个常数,根据常数group by

没有意义,所以去掉group by。

select user_id,count(*) as count from comment where user_id=90

 除第4步没法根据EXPLAIN输出和查询性能判断出MySQL是否进行这一优化外,前3类优化MySQL都不会进行。所以,MySQL要可以有效的处理上述查询还有很长的路要走。


PS: 相对来讲PostgreSQL的查询优化能力就强得多,上面的查询在PostgreSQL中就可以产生上述优化后的最终执行计划。PostgreSQL比较关注查询优化估计与PostgreSQL的学院派风格或PostgreSQL中的rule system有关。
相关文章
相关标签/搜索