1. 程式人生 > >SQLServer之建立索引檢視

SQLServer之建立索引檢視

索引檢視建立注意事項

對檢視建立的第一個索引必須是唯一聚集索引。 建立唯一聚集索引後,可以建立更多非聚集索引。 為檢視建立唯一聚集索引可以提高查詢效能,因為檢視在資料庫中的儲存方式與具有聚集索引的表的儲存方式相同。 查詢優化器可使用索引檢視加快執行查詢的速度。 要使優化器考慮將該檢視作為替換,並不需要在查詢中引用該檢視。

索引檢視中列的 large_value_types_out_of_row 選項的設定繼承的是基表中相應列的設定。 此值是使用 sp_tableoption設定的。從表示式組成的列的預設設定為 0。 這意味著大值型別儲存在行內。

可以對已分割槽表建立索引檢視,並可以由其自行分割槽。

若要防止 資料庫引擎 使用索引檢視,請在查詢中包含 OPTION (EXPAND VIEWS) 提示。 此外,任何所列選項設定不正確均會阻止優化器使用檢視上的索引。 有關 OPTION (EXPAND VIEWS) 提示的詳細資訊,請參閱 SELECT (Transact-SQL)。

若刪除檢視,該檢視的所有索引也將被刪除。 若刪除聚集索引,檢視的所有非聚集索引和自動建立的統計資訊也將被刪除。 檢視中使用者建立的統計資訊受到維護。 非聚集索引可以分別刪除。 刪除檢視的聚集索引將刪除儲存的結果集,並且優化器將重新像處理標準檢視那樣處理檢視。

可以禁用表和檢視的索引。 禁用表的聚集索引時,與該表關聯的檢視的索引也將被禁用。

索引檢視建立要求

建立索引檢視需要執行下列步驟並且這些步驟對於成功實現索引檢視而言非常重要:

  1. 驗證是否檢視中將引用的所有現有表的 SET 選項都正確。

  2. 在建立任意表和檢視之前,驗證會話的 SET 選項設定是否正確。

  3. 驗證檢視定義是否為確定性的。

  4. 使用 WITH SCHEMABINDING 選項建立檢視。

  5. 為檢視建立唯一的聚集索引。

索引檢視所需的 SET 選項

如果執行查詢時啟用不同的 SET 選項,則在 資料庫引擎 中對同一表示式求值會產生不同結果。 例如,將 SET 選項 CONCAT_NULL_YIELDS_NULL 設定為 ON 後,表示式 ' abc ' + NULL 會返回值 NULL。 但將 CONCAT_NULL_YIEDS_NULL 設定為 OFF 後,同一表示式會生成 ' abc '。

為了確保能夠正確維護檢視並返回一致結果,索引檢視需要多個 SET 選項具有固定值。 下表中的 SET 選項必須設定中顯示的值為RequiredValue列出現以下情況時:

  • 建立檢視和檢視上的後續索引。

  • 在建立表時,在檢視中引用的基表。

  • 對構成該索引檢視的任何表執行了任何插入、更新或刪除操作。 此要求包括大容量複製、複製和分散式查詢等操作。

  • 查詢優化器使用該索引檢視生成查詢計劃。

    SET 選項 必需的值 預設伺服器值 ,則“預設”

    OLE DB 和 ODBC 值
    ,則“預設”

    DB-Library 值
    ANSI_NULLS ON ON ON OFF
    ANSI_PADDING ON ON ON OFF
    ANSI_WARNINGS* ON ON ON OFF
    ARITHABORT ON ON OFF OFF
    CONCAT_NULL_YIELDS_NULL ON ON ON OFF
    NUMERIC_ROUNDABORT OFF OFF OFF OFF
    QUOTED_IDENTIFIER ON ON ON OFF

    *將 ANSI_WARNINGS 設定為 ON 隱式將 ARITHABORT 設定為 ON。

    如果使用的是 OLE DB 或 ODBC 伺服器連線,則唯一必須要修改的值是 ARITHABORT 設定。 必須使用 sp_configure 在伺服器級別或使用 SET 命令從應用程式中正確設定所有 DB-Library 值。極力建議在伺服器的任一資料庫中建立計算列的第一個索引檢視或索引後,儘早在伺服器範圍內將 ARITHABORT 使用者選項設定為 ON。

確定性檢視

索引檢視的定義必須是確定性的。 如果選擇列表中的所有表示式、WHERE 和 GROUP BY 子句都具有確定性,則檢視也具有確定性。 在使用特定的輸入值集對確定性表示式求值時,它們始終返回相同的結果。 只有確定性函式可以加入確定性表示式。 例如,DATEADD 函式是確定性函式,因為對於其三個引數的任何給定引數值集它總是返回相同的結果。 GETDATE 不是確定性函式,因為總是使用相同的引數呼叫它,而它在每次執行時返回結果都不同。

要確定檢視列是否為確定性列,請使用 COLUMNPROPERTY 函式的 IsDeterministic 屬性。 使用 COLUMNPROPERTY 函式的 IsPrecise 屬性確定具有架構繫結的檢視中的確定性列是否為精確列。 如果為 TRUE,則 COLUMNPROPERTY 返回 1;如果為 FALSE,則返回 0;如果輸入無效,則返回 NULL。 這意味著該列不是確定性列,也不是精確列。

即使是確定性表示式,如果其中包含浮點表示式,則準確結果也會取決於處理器體系結構或微程式碼的版本。 為了確保資料完整性,此類表示式只能作為索引檢視的非鍵列加入。 不包含浮點表示式的確定性表示式稱為精確表示式。 只有精確的確定性表示式才能加入鍵列,幷包含在索引檢視的 WHERE 或 GROUP BY 子句中。

其他要求

除對 SET 選項和確定性函式的要求外,還必須滿足下列要求:

    • 執行 CREATE INDEX 的使用者必須是檢視所有者。

    • 建立索引時,IGNORE_DUP_KEY 選項必須設定為 OFF(預設設定)。

    • 在檢視定義中,表必須由兩部分組成的名稱(即 schema.tablename**)引用。

    • 必須已使用 WITH SCHEMABINDING 選項建立了在檢視中引用的使用者定義函式。

    • 檢視中引用的任何使用者定義函式都必須由兩部分組成的名稱(即 schema.function**)引用。

    • 使用者定義函式的資料訪問屬性必須為 NO SQL,外部訪問屬性必須是 NO。

    • 公共語言執行時 (CLR) 功能可以出現在檢視的選擇列表中,但不能作為聚集索引鍵定義的一部分。 CLR 函式不能出現在檢視的 WHERE 子句中或檢視中的 JOIN 運算的 ON 子句中。

    • 在檢視定義中使用的 CLR 函式和 CLR 使用者定義型別方法必須具有下表所示的屬性設定。

      “屬性” 注意
      DETERMINISTIC = TRUE 必須顯式宣告為 Microsoft .NET Framework 方法的屬性。
      PRECISE = TRUE 必須顯式宣告為 .NET Framework 方法的屬性。
      DATA ACCESS = NO SQL 通過將 DataAccess 屬性設定為 DataAccessKind.None 並將 SystemDataAccess 屬性設定為 SystemDataAccessKind.None 來確定。
      EXTERNAL ACCESS = NO 對於 CLR 例程,該屬性的預設設定為 NO。
    • 必須使用 WITH SCHEMABINDING 選項建立檢視。

    • 檢視必須僅引用與檢視位於同一資料庫中的基表。 檢視無法引用其他檢視。

    • 檢視定義中的 SELECT 語句不能包含下列 Transact-SQL 元素:

      COUNT ROWSET 函式(OPENDATASOURCE、OPENQUERY、OPENROWSET 和 OPENXML) OUTER 聯接(LEFT、RIGHT 或 FULL)
      派生表(通過在 FROM 子句中指定 SELECT 語句來定義) 自聯接 通過使用 SELECT * 或 SELECT table_name來指定列。*
      DISTINCT STDEV、STDEVP、VAR、VARP 或 AVG 公用表表達式 (CTE)
      float*text, ntext, image, XML,或filestream 子查詢 包括排名或聚合開窗函式的 OVER 子句
      全文謂詞(CONTAIN、FREETEXT) 引用可為 Null 的表示式的 SUM 函式 ORDER BY
      CLR 使用者定義聚合函式 返回頁首 CUBE、ROLLUP 或 GROUPING SETS 運算子
      MIN、MAX UNION、EXCEPT 或 INTERSECT 運算子 TABLESAMPLE
      表變數 OUTER APPLY 或 CROSS APPLY PIVOT、UNPIVOT
      稀疏列集 內聯或多語句表值函式 OFFSET
      CHECKSUM_AGG

      *索引的檢視可以包含float列; 但是,不能在聚集的索引鍵中包含此類列。

    • 如果存在 GROUP BY,則 VIEW 定義必須包含 COUNT_BIG(*),並且不得包含 HAVING。 這些 GROUP BY 限制僅適用於索引檢視定義。 即使一個索引檢視不滿足這些 GROUP BY 限制,查詢也可以在其執行計劃中使用該檢視。

    • 如果檢視定義包含 GROUP BY 子句,則唯一聚集索引的鍵只能引用 GROUP BY 子句中指定的列。

使用SSMS資料庫管理工具建立索引檢視

1、連線資料庫,選擇資料庫,展開資料庫-》右鍵檢視-》選擇新建檢視。

2、在新增表彈出框-》選擇要建立檢視的表、檢視、函式、或者同義詞等-》點選新增-》新增完成後選擇關閉。

3、在關係圖窗格中-》選擇表與表之間關聯的資料列-》選擇列的其他排序或篩選條件。

4、右鍵點選空白處-》選擇屬性。

5、在檢視屬性窗格-》繫結到架構選擇是-》非重複值選擇是。

6、點選儲存或者ctrl+s-》檢視新建立的檢視。

7、在物件資源管理器視窗-》展開檢視-》選擇檢視-》右鍵點選索引-》選擇新建索引-》選擇聚集索引。

8、在新建索引彈出框-》選擇索引資料列-》索引建立步驟可以參考本博主的建立索引博文-》點選確定(建立唯一聚集索引之後才能建立非聚集索引)。

9、在物件資源管理器中檢視檢視中的索引。

10、重新整理檢視-》可以建立非聚集索引,步驟同建立聚集索引(此處省略建立非聚集索引)。

11、點選儲存或者ctrl+s-》重新整理檢視-》檢視結果。

12、使用檢視。

使用T-SQL指令碼建立索引檢視

語法:

--宣告資料庫引用
use 資料庫;
go

--判斷檢視是否存在,如果存在則刪除
if exists(select * from sys.views where name=檢視名稱)
drop view 檢視名稱;
go

--建立檢視
create
view

--檢視所屬架構的名稱。
--[schema_name][.]

--檢視名稱。 檢視名稱必須符合有關識別符號的規則。 可以選擇是否指定檢視所有者名稱。
[dbo][.]檢視名稱

--檢視中的列使用的名稱。 僅在下列情況下需要列名:列是從算術表示式、函式或常量派生的;兩個或更多的列可能會具有相同的名稱(通常是由於聯接的原因);檢視中的某個列的指定名稱不同於其派生來源列的名稱。 還可以在 SELECT 語句中分配列名。
--如果未指定 column,則檢視列將獲得與 SELECT 語句中的列相同的名稱。
--column

with

--適用範圍: SQL Server 2008 到 SQL Server 2017 和 Azure SQL Database。
--對 sys.syscomments 表中包含 CREATE VIEW 語句文字的項進行加密。 使用 WITH ENCRYPTION 可防止在 SQL Server 複製過程中釋出檢視。
--encryption,

--將檢視繫結到基礎表的架構。 如果指定了 SCHEMABINDING,則不能按照將影響檢視定義的方式修改基表或表。 必須首先修改或刪除檢視定義本身,才能刪除將要修改的表的依賴關係。
--使用 SCHEMABINDING 時,select_statement 必須包含所引用的表、檢視或使用者定義函式的兩部分名稱 (schema.object)。 所有被引用物件都必須在同一個資料庫內。
--不能刪除參與了使用 SCHEMABINDING 子句建立的檢視的檢視或表,除非該檢視已被刪除或更改而不再具有架構繫結。 否則, 資料庫引擎將引發錯誤。 
--另外,如果對參與具有架構繫結的檢視的表執行 ALTER TABLE 語句,而這些語句又會影響檢視定義,則這些語句將會失敗。
schemabinding

--指定為引用檢視的查詢請求瀏覽模式的元資料時, SQL Server 例項將向 DB-Library、ODBC 和 OLE DB API 返回有關檢視的元資料資訊,而不返回基表的元資料資訊。 
--瀏覽模式元資料是 SQL Server 例項向這些客戶端 API 返回的附加元資料。 如果使用此元資料,客戶端 API 將可以實現可更新客戶端遊標。 瀏覽模式的元資料包含結果集中的列所屬的基表的相關資訊。
--對於使用 VIEW_METADATA 建立的檢視,瀏覽模式的元資料在描述結果集內檢視中的列時,將返回檢視名,而不返回基表名。
--當使用 WITH VIEW_METADATA 建立檢視時,如果該檢視具有 INSTEAD OF INSERT 或 INSTEAD OF UPDATE 觸發器,則檢視的所有列(timestamp 列除外)都可更新。 有關可更新檢視的詳細資訊,請參閱“備註”。
--view_metadata

--指定檢視要執行的操作。
as
select_statement
go

--建立索引詳情請參考索引部落格
if not exists (select * from sys.indexes where name=索引名稱)
--設定索引
create
unique
clustered 
index 
索引名稱
on 
dbo.檢視名
(列名 [ asc | desc],列名  [ asc | desc],......);
go

示例:本示例演示在檢視上建立一個唯一聚集索引。

--宣告資料庫引用
use testss;
go

--判斷檢視是否存在,如果存在則刪除
if exists(select * from sys.views where name='indexview1')
drop view indexview1;
go

--建立檢視
create
view

--檢視所屬架構的名稱。
--[schema_name][.]

--檢視名稱。 檢視名稱必須符合有關識別符號的規則。 可以選擇是否指定檢視所有者名稱。
dbo.indexview1

--檢視中的列使用的名稱。 僅在下列情況下需要列名:列是從算術表示式、函式或常量派生的;兩個或更多的列可能會具有相同的名稱(通常是由於聯接的原因);檢視中的某個列的指定名稱不同於其派生來源列的名稱。 還可以在 SELECT 語句中分配列名。
--如果未指定 column,則檢視列將獲得與 SELECT 語句中的列相同的名稱。
--column

with

--適用範圍: SQL Server 2008 到 SQL Server 2017 和 Azure SQL Database。
--對 sys.syscomments 表中包含 CREATE VIEW 語句文字的項進行加密。 使用 WITH ENCRYPTION 可防止在 SQL Server 複製過程中釋出檢視。
--encryption,

--將檢視繫結到基礎表的架構。 如果指定了 SCHEMABINDING,則不能按照將影響檢視定義的方式修改基表或表。 必須首先修改或刪除檢視定義本身,才能刪除將要修改的表的依賴關係。
--使用 SCHEMABINDING 時,select_statement 必須包含所引用的表、檢視或使用者定義函式的兩部分名稱 (schema.object)。 所有被引用物件都必須在同一個資料庫內。
--不能刪除參與了使用 SCHEMABINDING 子句建立的檢視的檢視或表,除非該檢視已被刪除或更改而不再具有架構繫結。 否則, 資料庫引擎將引發錯誤。 
--另外,如果對參與具有架構繫結的檢視的表執行 ALTER TABLE 語句,而這些語句又會影響檢視定義,則這些語句將會失敗。
schemabinding

--指定為引用檢視的查詢請求瀏覽模式的元資料時, SQL Server 例項將向 DB-Library、ODBC 和 OLE DB API 返回有關檢視的元資料資訊,而不返回基表的元資料資訊。 
--瀏覽模式元資料是 SQL Server 例項向這些客戶端 API 返回的附加元資料。 如果使用此元資料,客戶端 API 將可以實現可更新客戶端遊標。 瀏覽模式的元資料包含結果集中的列所屬的基表的相關資訊。
--對於使用 VIEW_METADATA 建立的檢視,瀏覽模式的元資料在描述結果集內檢視中的列時,將返回檢視名,而不返回基表名。
--當使用 WITH VIEW_METADATA 建立檢視時,如果該檢視具有 INSTEAD OF INSERT 或 INSTEAD OF UPDATE 觸發器,則檢視的所有列(timestamp 列除外)都可更新。 有關可更新檢視的詳細資訊,請參閱“備註”。
--view_metadata

--指定檢視要執行的操作。
as
select a.id,a.age,a.height,a.name,b.id as classid from dbo.test1 as a
inner join dbo.test3 as b on a.classid=b.id
--要求對該檢視執行的所有資料修改語句都必須符合 select_statement 中所設定的條件。 通過檢視修改行時,WITH CHECK OPTION 可確保提交修改後,仍可通過檢視看到資料。
--with check option;
go


if not exists (select * from sys.indexes where name='umiqueindexview1')
--設定索引
create
unique
clustered 
index 
umiqueindexview1
on 
dbo.indexview1
(name asc);
go

示例結果:因為資料量太小,查詢時間和效果不是很明顯。