在前面我們已經提到過有關視圖的下述觀點:由於視圖返回的結果集與具有行列結構的表有著相同的表格形式,並且我們可以在SQL 語句中像引用表那樣引用視圖,所以我們常把視圖稱為虛表。標准視圖的結果集並不以表的形式存儲在數據庫中,而是在執行引用了視圖的查詢時,SQL Server 2000 才把相關的基本表中的數據合並成視圖的邏輯結構。
上面的結論常讓我們產生這樣的焦慮:由於是在執行了引用了視圖的查詢時,SQL Server 2000 才把相關的基本表中的數據合並成視圖的邏輯結構,那麼當查詢所引用的視圖包含大量的數據行或涉及到對大量數據行進行合計運算或連接操作,毋庸置疑,動態地創建視圖結果集將給系統帶來沉重的負擔,尤其是經常引用這種大容量視圖。
解決這一令人頭痛問題的方法就是為視圖創建聚簇索引,只有這樣才會顯著地提高系統的性能。當在視圖上創建了聚簇索引後,視圖的結果集與有聚簇索引的表的數據集一樣是存儲在數據中的。
此外,在視圖上創建索引還會帶來這樣的好處;優化器可以在那些在FROM 從句中不直接命名視圖的查詢中使用視圖索引,而且對已存在的視圖而言,由於不必重新編寫查詢代碼,從而提高了查詢從索引視圖中檢索數據的效率。
如果在視圖上創建索引,那麼視圖中的數據會被立即存儲在數據庫中,對索引視圖進行修改,那麼這些修改會立即反映到基礎表中。同理,對基礎表所進行的數據修改也會反映到索引視圖那裡。索引的惟一性大大提高了SQL Server 查找那些被修改的數據行。
維護索引視圖比維護基礎表的索引更為復雜。所以,如果認為值得以因數據修改而增加系統負擔為代價來提高數據檢索的速度,那麼應該在視圖上創建索引。在為視圖創建索引前,視圖本身必須滿足以下條件: 在執行CREATE VIEW 命令時,必須將ANSI_NULLS 和QUOTED_IDENTIFIER選項設置為ON 狀態; 在使用CREATE TABLE 命令創建索引所引用的基礎表時,ANSI_NULLS 選項應設置為ON; 該視圖所引用的對象僅包括基礎表而不包括其它的視圖; 視圖所引用的基礎表必須與視圖同屬於同一數據庫且有相同的所有者; 在創建視圖時必須使用SCHEMABINDING 選項; 如果視圖引用了用戶自定義函數,那麼在創建這些用戶自定義函數時也必須使用SCHEMABINDING 選項 ; 視圖必須以owner.objectname 的形式來使所引用的表或用戶自定義函數; 視圖所引用的函數必須是確定性的; 另外值得注意的是,在創建視圖的SELECT 語句中不應該包含下面的Transact-SQL語法; SELECT 語句中不能使用*或tablename.*來定義列,必須直接給出列名,否則不可以; 表示行集合的函數; UNION、 DISTINCT、 TOP、 ORDER BY、 COMPUTE、 COMPUTE BY、COUNT(*) 等; AVG、 MAX、 MIN、 STDEV、 STDEVP、 VAR 和VARP 等合計運算函數。
通常而言,可以在視圖上創建多個索引,但是應該記住,在視圖上所創建的第一個索引必須是聚簇索引,然後才可以創建其它的非聚簇索引。
在第八章我們已經詳細介紹了CREATE INDEX 命令但是如果准備為視圖創建索引那麼在執行該命令以前您必須確保以下條件否則創建將會失敗。 CREATE INDEX 命令的執行者必須是視圖的所有者; 在執行創建索引命令期間,ANSI_NULLS、 ANSI_PADDING、 ANSI_WARNINGS、ARITHABORT、 CONCAT_NULL_YIELDS_NULL、 QUOTED_IDENTIFIERS 諸選項應被設置成ON 狀態; NUMERIC_ROUNDABORT 選項被設置為OFF 狀態; 視圖不能包括text、 ntext、 image 類型的數據列; 如果視圖的SELECT 語句中包含ORDER BY 選項,則聚簇索引的關鍵值只能是ORDER BY 從句中所定義的數據列。
在視圖上創建了索引之後,如果打算修改視圖數據,則應該保證修改時的選項設置與創建索引時的選項設置一樣,否則SQL Server 將產生錯誤信息,並回滾所做的INSERT、UPDATE 和DELETE 操作。