Die Geschwindigkeit einer insert
-Anweisung hängt im Wesentlichen von der Anzahl der Indizes auf der Tabelle ab. Je mehr Indizes, desto langsamer die Ausführung. Da die insert
-Anweisung keine where
-Klausel hat, ist sie die einzige Operation, die keinen direkten Nutzen aus der Indizierung ziehen kann.
Um eine neue Zeile in eine Tabelle einzufügen, muss die Datenbank zuerst einen passenden Speicherplatz finden. Bei einer normalen Heap-Tabelle – deren Einträge nicht sortiert sind – genügt dafür der erstbeste Tabellenblock, der ausreichend Speicherplatz frei hat. Das ist ein sehr einfacher und schneller Vorgang, der oft im Hauptspeicher ausgeführt werden kann. Danach muss die Datenbank den Eintrag nur noch in den entsprechenden Block schreiben.
Wenn es aber einen, oder gar mehrere, Indizes auf der Tabelle gibt, muss die Datenbank sicherstellen, dass der neue Eintrag auch über einen Index gefunden werden kann. Daher muss der neue Tabelleneintrag in jeden Index dieser Tabelle nachgetragen werden. Die Anzahl der Indizes ist also ein Multiplikator für den Aufwand einer insert
-Anweisung.
Hinweis in eigener Sache
Ich biete SQL Schulungen, Optimierung und Beratung an. Auch der Kauf meines Buches „SQL Performance Explained“ (ab €9,95) unterstützt meine Arbeit an dieser Webseite.
Darüber hinaus ist das Einfügen in einen Index ungleich aufwendiger als das Einfügen in eine Heap-Struktur. Schließlich müssen die Indexreihenfolge und das Gleichgewicht (balance) gewahrt bleiben. Der neue Eintrag kann also nicht an eine beliebige Stelle geschrieben werden, sondern gehört in einen ganz bestimmten Blattknoten. Obwohl die Datenbank den Indexbaum selbst verwendet, um den richtigen Blattknoten zu finden, erfordert das alleine schon einige Lesezugriffe.
Wenn der korrekte Blattknoten gefunden wurde, muss noch geprüft werden, ob er ausreichend freien Speicherplatz bietet. Wenn nicht, müssen die bestehenden Einträge auf zwei Blattknoten aufgeteilt werden („leaf node split“). Davon ist natürlich auch der Eintrag im darüberliegenden Zweigknoten betroffen, der ebenfalls geteilt werden muss. Unnötig zu erwähnen, dass auch dabei der Platz ausgehen kann, sodass auch dieser Knoten aufgeteilt werden muss. Im schlimmsten Fall setzt sich das Aufteilen der Indexblöcke bis zum Wurzelknoten fort („root node split“) – dem einzigen Fall, in dem der Indexbaum tiefer wird.
Insgesamt stellt das Einfügen in die Indizes den Hauptaufwand einer insert
-Operation dar. Das ist auch in Abbildung 8.1 gut ersichtlich. Bei einer Tabelle ohne Index ist die Ausführungszeit im Chart kaum zu erkennen. Ein einziger Index genügt aber schon, damit die Ausführungszeit der insert
-Anweisung auf das Hundertfache ansteigt. Jeder weitere Index bremst die Ausführung weiter ab.
Abbildung 8.1 Insert-Performance abhängig von der Indexzahl

Beachte
Der erste Index macht den größten Unterschied.
Zur Optimierung einer insert
-Anweisung ist es also wichtig, die Anzahl der Indizes klein zu halten.
Tipp
Setze Indizes gezielt, aber sparsam ein und vermeide redundante Indizierung. Davon profitieren auch delete
- und update
-Anweisungen.
Wenn man nur insert
-Anweisungen betrachtet, wäre es ideal, gar keinen Index anzulegen. Damit erhält man die mit Abstand beste insert
-Performance. In realen Anwendungen sind Tabellen ohne Index jedoch ausgesprochen unrealistisch. In der Regel möchte man die gespeicherten Daten später auch wieder auslesen, sodass eine Indizierung für die select
-Abfragen wünschenswert ist. Selbst die einfachsten Tabellen brauchen zumindest einen Index für den Primärschlüssel.
Da der Performancegewinn ohne Index dermaßen eklatant ist, kann es sich zum Laden großer Datenmengen auszahlen, alle Indizes während des Ladens zu löschen – vorausgesetzt, die Indizes werden in dieser Zeit nicht für andere SQL-Anweisungen benötigt. Dadurch kann man den sprunghaften Performancegewinn, der im Chart sichtbar ist, realisieren. Diese Vorgehensweise ist im Datawarehouse-Bereich durchaus üblich.
Denksport
Wie würde sich Abbildung 8.1 ändern, wenn man eine Index-organisierte Tabelle oder einen Clustered-Index verwendet?
Gibt es vielleicht einen indirekten Weg, auf dem eine insert
-Anweisung von Indizierung profitieren kann – das Einfügen durch einen zusätzlichen Index also schneller wird?