View’lere index ekleyerek Indexed View’leri elde ederiz. View kavramı hakkında detaylı bilgi almak için “ View Nedir Ve Nasıl Oluşturulur ” isimli makalemi okumanızı tavsiye ederim.
View’ler normalde verinin kendisini tutmazlar. View’leri indexed view hale getirdiğimizde artık verinin kendisini tutmaya başlarlar. Bu yüzden view performansı artarken view’in select ettiği tabloların insert,update ve delete performansları azalır. Ayrıca indexed view’ler veritabanınızda ekstra alan kaplamaya başlar. View’leri indexed view hale getirmek için bazı şartlar vardır. Bu şartları aşağıda maddelere halinde sıralayalım.
1) Schemabinding yapıya geçirmek ya da oluştururken schemabinding yapıda oluşturmak gerekir. Schemabinding’in mantığı view’in select ettiği tablolarda bir modifikasyon değişikliği yapılamaz olması. Schemabinding yapıda view’i oluşturduktan sonra view’in select ettiği tablolardaki kolonlarda aşağıdaki gibi bir modifikasyon yapılmak istendiğinde aşağıdaki gibi bir hata alırsınız.
ALTER TABLE dbo.IdentitiyOrnekTablo ALTER COLUMN ID bigint;
Msg 5074, Level 16, State 1, Line 6
The object ‘IndexedViewOrnek’ is dependent on column ‘ID’.
Msg 4922, Level 16, State 9, Line 6
ALTER TABLE ALTER COLUMN ID failed because one or more objects access this column.
View’i schemabinding yapıda yeni oluştururken aşağıdaki gibi oluşturmamız gerekir.
CREATE VIEW [dbo].[IndexedViewOrnek] WITH SCHEMABINDING AS SELECT ID,AdSoyad FROM [dbo].[IdentitiyOrnekTablo]
Schemabinding ile oluşturulmamış bir view’i schemabinding yapıya aşağıdaki script ile çevirebiliriz.
ALTER VIEW [dbo].[IndexedViewOrnek] WITH SCHEMABINDING AS SELECT ID,AdSoyad FROM [dbo].[IdentitiyOrnekTablo]
2) View’i oluşturacak Select ifadesinde * FROM yerine kolonları tek tek yazmalısınız. Yoksa aşağıdaki gibi hata alırsınız.
Msg 1054, Level 15, State 6, Procedure IndexedViewOrnek, Line 4
Syntax ‘*’ is not allowed in schema-bound objects.
3) View’i schemabinding yapıda oluşturduktan sonra ilk olarak unique clustered index eklemeniz gerekir. Unique clustered index ekledikten sonra diğer kolonlara da index koyabilirsiniz. Aşağıdaki script ile unique clustered index koyma işlemini gerçekleştirebilirsiniz.
CREATE UNIQUE CLUSTERED INDEX UIX_IndexedViewOrnek ON dbo.IndexedViewOrnek(ID); GO
Biz örneğimizde ID kolonu üzerinde unique clustered index koymayı tercih ettik. Sizde bu seçimi yaparken seçeceğiniz kolonun view’in select ettiği tabloda da unique olduğundan emin olun. Yoksa aşağıdaki gibi hata alırsınız.
Msg 1505, Level 16, State 1, Line 1
The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for the object name ‘IndexedViewOrnek’ and the index name ‘UIX_IndexedViewOrnek’. The duplicate key value is (182861, C740D0288EA7C45FE0407C0A04162BDD, 12685525396).
The statement has been terminated.
4) View’i oluştururken select sorgunuzda aşağıdaki tabloda belirtilen ifadeleri kullanamazsınız.
COUNT |
ROWSET function’ları (OPENDATASOURCE, OPENQUERY, OPENROWSET, AND OPENXML) |
OUTER join çeşitleri (LEFT, RIGHT, veya FULL) |
Derived table |
Self-joins |
* |
DISTINCT |
STDEV, STDEVP, VAR, VARP, or AVG |
Common table expression (CTE) |
float *, text , ntext , image , XML , veya filestream kolonları |
Subquery |
OVER |
Full-text predicates (CONTAIN, FREETEXT) |
SUM function that references a nullable expression |
ORDER BY |
CLR user-defined aggregate function |
TOP |
CUBE, ROLLUP, veya GROUPING SETS operatörleri |
MIN, MAX |
UNION, EXCEPT, or INTERSECT operators |
TABLESAMPLE |
Table variables |
OUTER APPLY or CROSS APPLY |
PIVOT, UNPIVOT |
Sparse kolon |
Inline veya multi-statement table-valued functions |
OFFSET |
Örnek olarak UNION, INTERSECT veya EXCEPT kullanırsanız view üzerinde bir önceki maddede bahsettiğimiz unique clustered index’i oluştururken aşağıdaki gibi hata alırsınız.
Msg 10116, Level 16, State 1, Line 1
Cannot create index on view ‘dbo.IndexedViewOrnek’ because it contains one or more UNION, INTERSECT, or EXCEPT operators. Consider creating a separate indexed view for each query that is an input to the UNION, INTERSECT, or EXCEPT operators of the original view.
Yada Common Table Expression kullanırsanız index oluştururken aşağıdaki gibi hata alırsınız.
Msg 10137, Level 16, State 1, Line 1
Cannot create index on view “dbo.IndexedViewOrnek” because it references common table expression “TBL_CTE”. Views referencing common table expressions cannot be indexed. Consider not indexing the view, or removing the common table expression from the view definition.
5) View’lerin tablo ile aynı sonuç kümesini döndürmesi için SET seçeneklerine dikkat etmeniz gerekir. Çünkü farklı SET seçenekleri farklı sonuçlar doğurabilir. Örneğin SET CONCAT_NULL_YIELDS_NULL ON ifadesi view’in başında olursa select ifadesinde ‘x’+null dediğinizde sonuç null gelecektir. SET CONCAT_NULL_YIELDS_NULL OFF ifadesi view’in başında olursa bu değer bu sefer x olarak dönecektir.
Olması gereken SET seçeneklerini aşağıdaki tabloda görebilirsiniz. Aslında default olarak server’daki ile aynı fakat
OLE DB ya da ODBC connection kullanıyorsanız bazı değişiklikler yapmanız gerekiyor. Aşağıdaki tabloda olması gereken değerler ve default değerleri görebilirsiniz.
SET options |
Olması Gereken Değer |
Default Değer |
Default
OLE DB ve ODBC Değeri |
Default
DB-Library Değeri |
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 |
6) View’i oluşturan select sorgusunda tabloları select ederken tablo ismini şema ismi ile birlikte schema.tablename şeklinde yazmalısınız. Bu şekilde yazmazsanız aşağıdaki gibi hata alırsınız.
Msg 4512, Level 16, State 3, Procedure IndexedViewOrnek, Line 4
Cannot schema bind view ‘dbo.IndexedViewOrnek’ because name ‘IdentitiyOrnekTablo’ is invalid for schema binding. Names must be in two-part format and an object cannot reference itself.
7) Eğer view içersinde user defined functions kullanıyorsanız bu fonksiyonu da şema ismi ile birlikte schema.function şeklinde kullanmalısınız.
8) Eğer sorguda GROUP BY kullanırsanız select ifadesinde COUNT_BIG(*) ifadesinide kullanmalı, HAVING kullanmamalısınız. Örnek olarak;
CREATE VIEW [dbo].[IndexedViewOrnek] WITH SCHEMABINDING AS SELECT SUM(ID) ToplamID,AdSoyad,COUNT_BIG(*) sayı FROM [dbo].[IdentitiyOrnekTablo] GROUP BY AdSoyad
Eğer indexed view oluştururken Group By kullandığınızda COUNT_BIG(*) kullanmazsanız unique clustered index oluşturamazsanız. Aşağıdaki gibi bir hata ile karşılaşırsınız.
Msg 10138, Level 16, State 1, Line 1
Cannot create index on view ‘Test.dbo.IndexedViewOrnek’ because its select list does not include a proper use of COUNT_BIG. Consider adding COUNT_BIG(*) to select list.
9) Eğer view içersindeki select ifadesinde select edeceğiniz kolonları yazarken bir alias tanımlamazsanız aşağıdaki gibi bir hata alırsınız.
Hatalı view oluşturma script’i: Bu script’te ki hata SUM(ID) için bir alias tanımlanmamış olması.
Şöyle olmalıydı: SUM(ID) TOPLAMID
CREATE VIEW [dbo].[IndexedViewOrnek] WITH SCHEMABINDING AS SELECT SUM(ID),AdSoyad FROM [dbo].[IdentitiyOrnekTablo] GROUP BY AdSoyad
Hata:
Msg 4511, Level 16, State 1, Procedure IndexedViewOrnek, Line 14
Create View or Function failed because no column name was specified for column 1.