定義:視圖是從一個或幾個基本表導出的表,它與基本表不同,是一個虛表。
作用:
1.簡化操作,不用進行多表查詢。
2.當不同種類的用用戶共享同一個數據庫時,非常靈活,(用戶以不同的
方式看待同一數據.
3.視圖對重構數據庫提供了一定程度的邏輯獨立性。
數據的邏輯獨立性是指:如增加新的關系或對原有的關系增加新的
字段,用戶的應用程序不受影響.
例如:原有一個Student(Sno,Sname,Ssex,Sage,Sdept)這樣一個表.
后來變動為:Sx(Sno,Sname,Sage)和SY(Sno,Ssex,Sdept)
兩個表。
這時候原表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個視圖,每個視圖只包含一個院系的學生數據,並只允許每個院系的主任查詢和修改本原系學生視圖。
5、適當的利用視圖可以更清晰地表達查詢
例如經常需要執行這樣的查詢“對每個學生找出他獲得最高成績的課程號”。可以先定義一個視圖,求出每個同學獲得的最高成績: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語言中的宏展開.
例如設有以下表:
【一般在能夠使用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要能夠有效的處理上述查詢還有很長的路要走。