Collation & Data Type Precedence · 10 Mio. Zeilen
Implizite Konvertierung: 3 Reads gegen 27.469 Reads
Wenn eine Anwendung einen Unicode-Parameter (@p nvarchar, Standard in .NET/EF) gegen eine varchar-Spalte schickt, hängt das Verhalten an der Sortierung (Collation):
-
Optimal:
1,0 ms
(0 ms CPU)
·
3 Reads
(Index Seek)
-
Collation-Mismatch:
318 ms
(+2.120 ms CPU)
·
27.469 Reads
(Index Scan)
-
Typ-Mismatch (int):
287 ms
(+1.864 ms CPU)
·
27.469 Reads
(Index Scan)
Unter SQL-Sortierung oder bei varchar = int muss SQL Server jede einzelne Zeile umwandeln (Plan-Warnung: CONVERT_IMPLICIT). Aus 3 Seitengriffen und 0 ms CPU werden 27.469 Reads und über 2 Sekunden verbrannte CPU-Zeit je Einzelabfrage.
Mengenübergabe & Plan-Cache · 10 Mio. Zeilen
Lange IN-Listen (2.000 IDs) und Ad-hoc-Flut
Wie übergibt man Hunderte oder Tausende IDs aus C# an SQL Server? Ich habe vier Verfahren bei 10 bis 2.000 IDs und bei 50.000 Einzelaufrufen gegeneinander gemessen:
-
TVP (2.000 IDs):
172 ms
(0 ms Compile)
·
200 KB Cache
-
Literal-Liste:
591 ms
(196 ms Compile)
·
6.376 KB Cache
-
50.000 Ad-hoc:
781 MB Plan-Müll vs. 0,1 MB (parametrisiert)
Einzelparameter (@p1 … @p1000) brechen schon bei 1.000 IDs durch Merge Interval / Concatenation auf 565 ms und 7,1 MB Plan-Größe ein. Table-Valued Parameters (TVP) liefern konstant einen wiederverwendbaren Plan ohne Kompilierlast.
Datenmodell & Speicher · 1 Mio. Kind- / 50.000 Elternzeilen
Zusammengesetzter Textschlüssel vs. Surrogate Key (int)
Ein dreiteiliger Fachschlüssel (Mandant + Bereich + Artikelnummer, im Schnitt 56 Zeichen) wiederholt sich in jeder Kindtabelle und in jedem Fremdschlüssel-Index:
-
Technischer int-Key:
0,3 ms
·
108 MB Speicher
(Faktor ×2,83 schlanker)
-
3-teiliger Textschlüssel:
18,3 ms
·
305 MB Speicher
(60× langsamer)
Der technische 4-Byte-Schlüssel spart fast zwei Drittel des Speicher- und Buffer-Pool-Bedarfs (während der Fachschlüssel als UNIQUE-Constraint auf der Elterntabelle erhalten bleibt). Für bestehende Kundendatenbanken habe ich ein Katalog-Skript entwickelt, das diese Ersparnis vorab rein aus sys.dm_db_partition_stats und sys.index_columns ohne Lese-Last auf den Nutzdaten berechnet.
SARGability · 10 Mio. Zeilen
Führender Platzhalter (LIKE '%berg'): von 4,2 s auf 3,3 ms
Eine Endungssuche wie WHERE Firma LIKE '%berg' ist nicht SARGable – selbst mit Index auf Firma liest SQL Server alle 49.062 Indexseiten (21.297 ms CPU-Zeit, 4.231 ms Laufzeit im Parallel-Scan).
-
REVERSE + Index:
3,3 ms
(0 ms CPU)
·
45 Reads
-
LIKE '%berg' (Scan):
4.231 ms
(21.297 ms CPU)
·
49.062 Reads
Mit einer berechneten Spalte FirmaRev AS REVERSE(Firma) und einem Index darauf wird aus der Endungssuche eine Präfixsuche (LIKE REVERSE(@p)). Die Lesevorgänge sinken von 49.062 auf 45 Reads (Faktor ×1.090 weniger I/O), die Laufzeit von 4.231 ms auf 3,3 ms (über ×1.200 schneller).
Server- & Datenbankgrenzen · 1 Mio. Zeilen
Linked Server vs. OPENQUERY und Collation-Falle
Abfragen über Server- und Datenbankgrenzen hinweg kippen je nach Selektivität und Sortierung in völlig unterschiedliche Ausführungspläne:
-
Gleiche Collation:
13 ms
·
66 Reads
(Index Seek)
-
Abweichende Collation:
1.383 ms
·
7.882 Reads
(Faktor ×119 I/O)
-
OPENQUERY (Punkt):
5,9 ms
·
(vs. 4-teilig: 210 ms · ×35 schneller)
Bei Einzelabfragen schiebt OPENQUERY den Filter auf den Zielserver; beim Gesamtverbund zwingt es dagegen in tausende lokale Nested-Loops-Seeks. Und weicht die Collation der Kinddatenbank ab, verhindert eine implizite Konvertierung den Index Seek (Faktor ×119 mehr Reads).
Normalisierung & Datenqualität · 1 Mio. Zeilen
Klartext-Spalten vs. Nachschlagetabellen (3NF)
Stehen Werte wie Stadt und Zahlungsart als Klartext in der Bewegungstabelle statt als int-Fremdschlüssel auf eine Nachschlagetabelle, leidet nicht nur die Geschwindigkeit:
-
Normalisiert:
15 ms
(432 Reads)
·
Widerspruchsprüfung:
2 ms
(28 Reads)
-
Klartext:
160 ms
(3.438 Reads)
·
Widerspruchsprüfung:
147 ms
(4.655 Reads)
Auf der kleinen Nachschlagetabelle (5.000 Städte) kostet selbst ein LIKE '%berg' fast nichts, bevor über die schlanke StadtId gejoint wird. Gleichzeitig verhindert das Modell abweichende Schreibweisen derselben Stadt zur selben Postleitzahl.