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有關。
相關文章
相關標籤/搜索