Auch wenn sich die Überschrift nach einem verspäteten Aprilscherz anhören mag, muss ich Sie leider enttäuschen. In diesem Blogeintrag geht es darum, die Inserts auf eine Tabelle zu beschleunigen. Viel Spaß beim Lesen.
Wie viele von euch vielleicht noch wissen, ging es in meinem Blogeintrag vom Oktober '13 um den SQL-Datentyp uniqueidentifier und dessen Nutzung als Primary Key-Spalte und somit als clustered Index. Laut dieses Blogeintrages sollte der uniqueidentifier nur im äußersten Notfall, für eine offline Anwendung oder globale ID, verwendet werden: Primary Key als GUID
Mittlerweile habe ich ein Szenario gefunden, indem es sogar von Vorteil wäre den Primary Key als uniqueidentifier und somit als clustered Index zu hinterlegen.
Problematik
Der uniqueidentifier-Datentyp ist leider viel zu groß, immerhin verbraucht er ganze 16byte Speicher pro Eintrag. Hinzu kommt das die Spalte des clustered Index in jedem non clustered Index enthalten ist, was die Tabellen/Datenbanken nur unnötig aufbläht.
Genaueres finden Sie in dem oben aufgeführtem Link.
Vorteil der GUID
Bestimmte Gegebenheiten müssen gewährleistet sein, damit die Vorteile der Performance optimal genutzt werden können. Umso mehr geschrieben wird, umso besser.
Das ich so was mal im Zusammenhang mit Indizes schreibe, hätte ich nie gedacht
Der Satz zuvor deutet schon ungefähr an um was es geht. In diesem Zusammenhang beschleunigt der Index das schreiben. Es müssen viele Inserts von verschiedenen Verbindungen stattfinden um einen Performancegewinn zu spüren.
Wie ist das möglich?
Pages, Pages und nochmal Pages.
Die Grafik zeigt eine Tabelle mit int Spalte, identity-Eigenschaft und clustered Index. auf der int-Spalte.
Da der clustered Index auf der int-Spalte gesetzt ist, sortiert der SQL Server die Einträge aufsteigend. Und genau darin besteht das Problem. Wenn nun mehrere Prozesse in die Tabelle schreiben wollen, können diese nur seriell geschrieben werden. D.h. ein Insert mit dem Wert “1” sperrt die Page bis der Datensatz geschrieben ist. Erst dann kann der Datensatz “2” geschrieben werden usw..
Nun werden sich einige von Ihnen denken, wieso indiziert man so eine Tabelle mit stark frequentierten Inserts? Denn es gilt folgende Regel: Schreibanteil > Leseanteil = kein Index, doch selbst ein HEAP, eine Tabelle ohne Index, fügt die Datensätze seriell ein.
Nun die Variante mit der GUID
Hier ein Uniqueidentifier als Datentyp und einen clustered Index auf der Spalte. Eine Sortierung erfolgt hier ebenfalls (in meiner Grafik nicht). Die kleinste GUID steht auf der Page 100, ganz vorne.
Jetzt folgt der Insert. Nehmen wir an es werden drei Datensätze eingefügt. Gehen wir davon aus das jeder diese Datensätze auf einer anderen Page landet, was bei einer GUID nicht unwahrscheinlich ist. Wenn dies so eintreten sollte, können alle drei Datensätze parallel geschrieben werden, was den Durchsatz enorm erhöht.
Ich hoffe ich konnte Ihnen den uniqueidentifier als clustered Index etwas schmackhafter reden/schreiben. Denken Sie jedoch an das Anwendungskriterium. Es müssen viele Datensätze geschrieben werden und zwar von verschiedenen Verbindungen.
Ich habe mir erlaubt ein paar Tests zu machen, die dieses Szenario bestätigen. Einen etwas erweiterten Beitrag und die Resultate der Tests finden Sie in der neuen Ausgabe der VS1.