Was ist eine indizierte Sicht? Was sind die
Anwendungsmöglichkeiten, Vor- und Nachteile? Damit beschäftigen wir uns in
diesem Artikel.
Anders als bei Tabellen, die physisch auf dem Datenträger
abgespeichert sind, fungiert eine Sicht (View) wie eine virtuelle Tabelle. Wir
können mit der Sicht zwar arbeiten, wie mit einer Tabelle, sie ist aber nicht in
der Datenbank abgespeichert. Wir haben in der Sicht gewissermaßen nur die Abfrage
hinterlegt, die stattfinden soll – aber die Sicht kann noch mehr.
Views (Sichten) werden zur Vereinfachung unseres
Arbeitsprozesses und nicht zuletzt aus Sicherheitsgründen verwendet. Zum einen
kann es eine große Arbeitserleichterung sein, bestimmte und eventuell
komplexere, häufig verwendete SELECT-Statements nicht ständig neu schreiben zu
müssen, sondern einfach die Sicht abzufragen; zum anderen können wir in der
Sicht ganz gezielt nur bestimmte Spalten abfragen und die Sicht zum
Sicherheitspuffer zwischen Datenbank und User machen.
Aber während die Sichten uns die Arbeit angenehmer machen,
vereinfachen sie die Arbeit für die Datenbank noch lange nicht; die abgefragten
Daten sind aktuell, die (eventuell sehr komplexen) SELECT-Statements laufen
trotzdem im Hintergrund ab, die entsprechenden Tabellen werden genauso
abgefragt, als würden wir ein normales SELECT-Statement schreiben, ohne, dass
im Hintergrund eine Performance-Optimierung stattfindet.
Das kann je nach Komplexität dazu führen, dass die Abfrage
langsam wird. Um dem gegenzusteuern, können wir auf der View einen eindeutigen
gruppierten Index (unique clustered index) erstellen. Damit wird die Abfrage
schneller, und auch andere Abfragen können davon profitieren.
Leider gibt es in SQL selten eine grandiose Premiumlösung für
alle Fälle, und auch die indizierte Sicht (indexed view) hat ihre Nachteile;
auf die kommen wir später noch einmal zu sprechen.
Sehen wir uns einmal an, wie wir eine indizierte Sicht
(indexed view) erstellen.
Vorab zu beachten, wenn wir eine indizierte Sicht erstellen
wollen:
·
Sicht
muss deterministisch sein (Näheres dazu in der Microsoft-Dokumentation.)
·
Verwenden
von WITH SCHEMABINDING
Deterministisch meint u.a., dass keine Funktionen in der View
enthalten sein dürfen, die jedes Mal ein anderes Ergebnis ausgeben, wie
beispielsweise GETDATE(). Versuchen wir, für so eine Sicht einen Index zu
erstellen, bekommen wir die Fehlermeldung „Cannot
create index on view 'viewname'. The function 'getdate' yields nondeterministic
results. Use a deterministic system function, or modify the user-defined
function to return deterministic results“.
With Schemabinding sorgt u.a. dafür, dass wir nicht eine
Tabelle löschen können, die von einer indizierten Sicht abgefragt wird (es wird
eine Fehlermeldung ausgegeben). In diesem Fall müsste erst die Sicht, dann erst
die Tabelle gelöscht werden.
Haben wir diese Dinge beachtet, ist das Erstellen des Index
einfach:
CREATE UNIQUE CLUSTERED INDEX IX_IndexName
ON v_Viewname(Spaltenname)
Bei größeren Datenmengen können wir damit die Anzahl der
gelesenen Seiten drastisch zurückschrauben, und der Index kann eventuell auch
anderweitig verwendet werden. Ist der eindeutige gruppierende Index (unique
clustered index) erstellt, können auch noch weitere nicht gruppierte
(non-clustered) Indizes auf der Sicht erstellt werden.
Beim Erstellen der indizierten Sicht gibt es noch einige
Stolpersteine. So dürfen zum Beispiel bestimmte TSQL-Elemente nicht enthalten
sein, u.a. COUNT, MIN oder MAX, und bestimmte Datentypen dürfen nicht für den
Index verwendet werden.
Ein Nachteil der indizierten Sicht ist natürlich, dass dieser
Index nun auch gewartet werden muss! Wir haben zwar unsere Abfrage schneller
gemacht, aber jedes Mal, wenn sich etwas an den beteiligten Tabellen ändert, müssen
nicht nur die Indizes der ursprünglichen Tabellen, sondern auch der Index/die
Indizes auf der Sicht upgedated werden.
Solche und ähnliche Themen besprechen wir auch in unseren
Kursen. Inzwischen viel Spaß beim Ausprobieren!