Storage Deep Dive:
IO-Stack, Latenzen und warum dein RAID-Controller lügt
Warum Storage immer noch der häufigste Performance-Killer ist
Wenn ein SQL Server langsam ist, tippen 80 % aller Admins sofort auf fehlende Indizes oder schlechte Abfragen. Manchmal stimmt das. Oft aber liegt das Problem tiefer — buchstäblich: auf der Festplatte, im SAN, im RAID-Controller. Storage ist die Komponente, die am häufigsten unterschätzt wird, am schlechtesten dokumentiert ist und am meisten Einfluss auf die Gesamtperformance hat.
Ein SQL Server liest und schreibt ständig. Der Buffer Pool hält zwar die "heißen" Seiten im RAM — aber, wenn eine Seite nicht gecacht ist, muss sie von der Platte kommen. Das Transaktionslog wird bei jedem Commit geschrieben, ohne Ausnahme. Backups lesen alles durch. Checkpoints schreiben die schmutzigen Seiten weg. Jede dieser Operationen hat eine Latenz, und diese Latenz summiert sich.
Konkrete Zahlen: Ein typischer OLTP-Server mit 500 Transaktionen pro Sekunde schreibt mindestens 500 Log-IOs pro Sekunde — synchron, denn SQL Server wartet auf die WRITELOG-Bestätigung. Wenn die Log-Latenz von 0,2 ms auf 15 ms steigt, verdreifacht sich die Transaktionsdauer. Der Nutzer bemerkt das. Der Kollege tippt auf "schlechte Nacht". Die Wahrheit liegt auf dem Spinnenplot der Latenzen.
In diesem Kapitel schauen wir uns den gesamten IO-Stack von SQL Server bis zum physischen Medium an, lernen die Latenz-Charakteristika der verschiedenen Medientypen kennen und bauen ein Werkzeugkasten an Diagnose-Werkzeugen auf. Für die tiefere Betrachtung der IO-Wait-Typen verweise ich auf Kapitel 9 (Wait Statistics) — dort werden PAGEIOLATCH_SH, PAGEIOLATCH_EX und WRITELOG im Detail behandelt. Und wer wissen will, was Sparfuchs & Partner aus all diesen Empfehlungen gemacht hat: Kapitel 33 liefert die Antwort.
Der IO-Stack: Von SQL Server bis zum Magnetkopf
Ein IO-Request durchläuft mehrere Software- und Hardware-Schichten, bevor er das Speichermedium erreicht. Jede Schicht kann Latenz addieren — oder sie kaschieren. Das ist der Grund, warum naive Messungen trügen können und warum der RAID-Controller manchmal lügt.

Abb. 2.1: Der vollständige IO-Stack: Von SQL Server bis zum physischen Medium
Schicht 1: SQL Server Storage Engine
SQL Server öffnet seine Datenbankdateien mit zwei kritischen Flags: FILE_FLAG_WRITE_THROUGH und FILE_FLAG_NO_BUFFERING. Das erste erzwingt, dass Schreiboperationen nicht im Windows-Cache verweilen — SQL Server will selbst kontrollieren, wann Daten wirklich auf dem Medium sind. Das zweite deaktiviert den Windows Cache Manager komplett: SQL Server verwaltet seinen eigenen Cache (den Buffer Pool), und will keine doppelte Pufferung.
Das Transaktionslog ist eine Sonderrolle: Es wird strikt sequenziell geschrieben. SQL Server schreibt Log-Blöcke und wartet auf WRITELOG-Completion, bevor er den Commit an den Client zurückmeldet. Kein Warten, kein Commit. Das macht das Log zur latenz-kritischsten Datei des gesamten Systems.
|
Definition: Write-Ahead Logging (WAL) |
|---|
|
SQL Server schreibt jede Änderung zuerst ins Transaktionslog, bevor die Datenseite im Buffer Pool als "dirty" markiert wird. Das garantiert Durability (das "D" in ACID) — aber kostet synchrone Log-IO. Wer das Log auf langsamen Storage legt, hat automatisch langsame Commits. |
Schicht 2: Windows I/O Manager und Dateisystem
NTFS ist für SQL Server-Daten fast immer die richtige Wahl — aber es gibt Details, die Performance kosten. Die wichtigste Einstellung: Allocationsunit-Größe. Für SQL Server-Datenbanken sollte sie 64 KB betragen (SQL Server's internes Seitenformat ist 8 KB, aber IO-Operationen laufen typisch in 64-KB-Blöcken). Standard-NTFS formatiert mit 4 KB — jeder IO wird dann in 16 Teiloperationen aufgespalten. Das kostet messbar: auf HDDs zwischen 5 und 20 % Durchsatzverlust.
|
Warnung: NTFS-Allocationsunit nicht vergessen |
|---|
|
Falsche Allocationsunit (4 KB statt 64 KB) kostet auf HDDs 5–20% Durchsatz. Auf SSDs und NVMe ist der Effekt kleiner, aber vorhanden. Einmal formatiert: nur durch Umformatieren zu korrigieren. Prüfen mit: fsutil fsinfo ntfsinfo D:\ |
Schicht 3: Treiber und Controller
Der Storage-Controller — ob onboard, PCIe-Karte oder HBA — ist der kritische Vermittler zwischen dem Software-Stack und dem physischen Medium. Er kann enormen Einfluss auf die beobachtete Latenz haben: Ein RAID-Controller mit Write-Back-Cache und Battery Backup Unit (BBU) kann Schreiblatenzen von 15 ms auf unter 0,5 ms drücken — weil er den Write sofort bestätigt und später asynchron auf das Medium schreibt. Das ist die "Lüge" aus dem Kapitel-Titel.
Was passiert, wenn der BBU leer oder defekt ist? Der Controller schaltet automatisch auf Write-Through um — und plötzlich sieht SQL Server die echte Medien-Latenz. Aus 0,5 ms werden 15 ms. Der DBA schaut verwirrt auf seinen Bildschirm. Der Server ist nicht "langsamer geworden" — er war die ganze Zeit langsam, nur wurde das kaschiert.
|
Tipp: BBU-Status überwachen |
|---|
|
RAID-Controller-BBU-Status ins Monitoring aufnehmen — nicht nur "Disk alive". Ein degradierter BBU ist der häufigste Grund für plötzliche, unerklärliche Performance-Verschlechterungen. Die meisten Controller-Hersteller bieten WMI-Provider oder Kommandozeilen-Tools (z.B. MegaRAID Storage Manager, HPE Array Diagnostic Utility). Diese Werte sollten in der Baseline aus Kapitel 9 erfasst sein. |
Latenzen: Was ist normal, was ist ein Problem?
Latenz ist die Zeitspanne zwischen dem Absetzen eines IO-Requests und der Rückkehr des Ergebnisses. Sie ist das wichtigste Maß für Storage-Performance — nicht Durchsatz. 100 MB/s klingt gut. Wenn die durchschnittliche Latenz dabei 80 ms beträgt, ist der Server trotzdem kaputt.
|
Medientyp |
Lese-Latenz (typisch) |
Schreib-Latenz |
Sequenzieller Durchsatz |
IOPS (random 4K) |
|---|---|---|---|---|
|
HDD (7.200 rpm) |
5–15 ms |
5–15 ms |
100–200 MB/s |
80–150 |
|
HDD (15.000 rpm) |
3–8 ms |
3–8 ms |
150–220 MB/s |
150–200 |
|
SSD (SATA) |
0,1–0,5 ms |
0,05–0,3 ms |
500–560 MB/s |
50.000–90.000 |
|
SSD (SAS/Enterprise) |
0,05–0,2 ms |
0,02–0,1 ms |
500–2.000 MB/s |
100.000–200.000 |
|
NVMe (Consumer) |
0,03–0,1 ms |
0,02–0,08 ms |
3.000–7.000 MB/s |
200.000–500.000 |
|
NVMe (Enterprise) |
0,02–0,05 ms |
0,01–0,03 ms |
6.000–12.000 MB/s |
500.000–2.000.000 |
|
Storage-Array (All-Flash) |
0,1–0,5 ms |
0,05–0,2 ms |
10–100 GB/s |
Millionen (gesamt) |
Tabelle 2.1: Latenz- und Durchsatz-Charakteristika verschiedener Speichermedien
Diese Zahlen sind Richtwerte für unbelastete Systeme. Unter Last — besonders bei zufälligem IO mit kleinen Blöcken (OLTP-typisch 8 KB) — sehen HDDs deutlich schlechter aus: p99-Latenzen von 50–100 ms sind keine Seltenheit. Das ist der Bereich, in dem Nutzer "langsame Anwendung" melden.
Schwellenwerte für SQL Server
Microsoft definiert in der Dokumentation zu sys.dm_io_virtual_file_stats keine offiziellen Schwellenwerte — aber die Community hat sich auf diese Faustregeln geeinigt:
|
Hintergrund: Warum der Durchschnitt lügt |
|---|
|
Latenzen sind typischerweise nicht normalverteilt, sondern long-tail: Viele Requests sind sehr schnell, wenige Requests sind sehr langsam. Der Durchschnitt wird von den schnellen dominiert. Deshalb: Immer p95 und p99 betrachten. sys.dm_io_virtual_file_stats liefert kumulierte Werte — für Percentilen braucht man Extended Events (Kapitel 8) oder eine Baseline aus Kapitel 9. |
RAID-Level: Performance-Charakteristik im Detail
RAID ist eine der am häufigsten missverstandenen Storage-Technologien. "RAID 5 ist gut, weil Redundanz" hört man oft — und das stimmt für Kapazitätseffizienz. Für schreibintensive Workloads ist RAID 5 eine toxische Beziehung.

Abb. 2.2: RAID-Level im Vergleich: Performance-Charakteristik für SQL Server
Die RAID-5 Write-Penalty: Vier IOs für einen logischen Write
RAID 5 speichert Daten mit Paritätsinformation. Bei einem Schreibvorgang muss der Controller:
Das sind vier physische IOs für einen logischen Schreibvorgang — der sogenannte "Read-Modify-Write-Cycle". Bei RAID 6 (doppelte Parität) sind es sogar sechs IOs. Auf Spindeln mit 7.200 rpm und 100 OLTP-Writes pro Sekunde bedeutet das 400 physische IO-Operationen — das übersteigt die IOPS-Kapazität der meisten HDD-Arrays problemlos.
Mit Write-Back-Cache des Controllers ist dieser Effekt versteckt — bis der Cache voll ist oder der BBU ausfällt. Dann sieht man die echte Charakteristik. Auf SSDs und NVMe ist die Penalty weniger dramatisch, weil der Controller die Berechnung schneller durchführt — aber sie ist weiterhin vorhanden.
|
Warnung: RAID 5/6 und SQL Server: Ein gefährliches Paar |
|---|
|
RAID 5 und 6 sollten nie für SQL Server-Datenbankdateien oder Transaktionslogs verwendet werden, wenn die Workload schreibintensiv ist. Der klassische Fall: 8 GB RAM, Priority Boost aktiviert, RAID 5 mit 7.200-rpm-Spindeln — und der Kollege fragt warum's langsam ist. RAID 10 ist die einzig vernünftige Wahl für produktive OLTP-Datenbanken. |
RAID 10: Warum es die erste Wahl ist
RAID 10 kombiniert Striping (RAID 0) und Mirroring (RAID 1). Jeder Write wird auf zwei Disks gespiegelt — das sind genau zwei physische IOs. Kein Read-Modify-Write, keine Paritätsberechnung. Die Kapazitätseffizienz ist schlechter (50% nutzbar), aber Performance und Resilienz sind optimal. Für SQL Server gilt: RAID 10 für Datendateien, RAID 10 (oder RAID 1) für das Transaktionslog.
Mit modernen SSDs und NVMe wird RAID weniger kritisch: Ein einzelner NVMe-Drive hat mehr IOPS als ein ganzes RAID-5-Array mit HDDs. Trotzdem bleibt Redundanz wichtig — und RAID 10 ist auch bei Flash die bevorzugte Wahl, weil der Overhead minimal ist.
DAS, SAN und NAS: Storage-Architekturen für SQL Server
SQL Server kann auf drei grundlegenden Storage-Architekturen betrieben werden. Jede hat spezifische Performance-Charakteristika, typische Fallstricke und einen Anwendungsbereich.
|
Architektur |
Protokoll |
Latenz |
Durchsatz |
Typischer Einsatz |
SQL-Server-tauglich |
|---|---|---|---|---|---|
|
DAS (Direct Attached) |
SATA/SAS/NVMe |
Sehr niedrig |
Sehr hoch |
Standalone-Server |
Ja — erste Wahl |
|
SAN (FC/iSCSI) |
Fibre Channel / iSCSI |
Niedrig–mittel |
Hoch |
Enterprise, Cluster |
Ja — mit Sorgfalt |
|
NAS (SMB 3.0) |
SMB 3.0 |
Mittel |
Mittel–hoch |
Dateiserver, Backup |
Eingeschränkt |
|
NAS (NFS) |
NFS v4.1 |
Mittel |
Mittel |
Linux/VMware |
Nicht empfohlen |
Tabelle 2.2: Storage-Architekturen im Vergleich
SAN: Hohe Leistung, hohe Komplexität
Storage Area Networks (SAN) ermöglichen es, Storage-Ressourcen zentral zu verwalten und zwischen Servern zu teilen. Das klingt gut — und ist es auch, wenn es richtig konfiguriert ist. Die typischen Fallstricke: Zu viele Hosts teilen dasselbe LUN, Queue-Depth-Einstellungen sind falsch, das Zoning ist suboptimal, oder der HBA-Treiber ist veraltet.
Fibre Channel bietet die niedrigsten Latenzen (0,1–0,3 ms Netzwerk-Overhead) und die höchste Zuverlässigkeit. iSCSI läuft über Standard-Ethernet und ist günstiger, hat aber höheren Protokoll-Overhead (0,2–1 ms, je nach Implementierung). Für SQL Server ist Fibre Channel bevorzugt, wenn hohe Transaktionsdichte gefragt ist.
NAS: Nur mit SMB 3.0
SQL Server unterstützt seit 2012 das Ablegen von Datenbankdateien auf SMB 3.0-Freigaben. Das funktioniert — aber nur, wenn das NAS entsprechend ausgelegt ist (dedizierte 10-GbE-Verbindung, All-Flash-Backend) und der SMB-3.0-Multichannel aktiviert ist. NFS ist für SQL Server unter Windows nicht unterstützt; unter Linux (Kapitel 7) gibt es Einschränkungen.
SQL Server IO-Muster: Was wann und wie viel
SQL Server ist kein homogener IO-Produzent. Je nach Operation sieht der IO-Stack sehr unterschiedliche Muster — und das beeinflusst die Wahl des Storage-Layouts erheblich.
|
Operation |
IO-Muster |
Blockgröße |
Latenz-kritisch? |
Anmerkung |
|---|---|---|---|---|
|
Datenlesen (OLTP) |
Random Read |
8 KB |
Ja |
Einzelne Seiten, nicht vorhersagbar |
|
Datenlesen (OLAP/Scan) |
Sequenzieller Read |
512 KB–8 MB |
Weniger |
Read-Ahead Mechanismus |
|
Transaktionslog schreiben |
Sequenzieller Write |
512 B–60 KB |
Sehr stark |
Synchron! WRITELOG ist kritisch |
|
Checkpoint (Daten) |
Random Write |
8 KB–64 KB |
Mäßig |
Asynchron, bulk write |
|
Backup lesen |
Sequenzieller Read |
64–1024 KB |
Weniger |
Liest alle Seiten durch |
|
Restore schreiben |
Sequenzieller Write |
64–1024 KB |
Weniger |
Parallelisierbar |
|
TempDB (Sorts/Spills) |
Random Read/Write |
8 KB–64 KB |
Ja |
Vermeidbar durch Tuning (Kap. 13) |
Tabelle 2.3: SQL Server IO-Muster nach Operation
Die wichtigste Erkenntnis: Das Transaktionslog ist sequenziell und latenz-kritisch. Es profitiert nicht von RAID-10-Striping (kein Random-IO), aber es braucht niedrige Latenz. Deshalb: Log auf einem dedizierten LUN oder einer dedizierten NVMe, weg von den Datendateien. Auch, wenn die Datendateien auf dem teuren All-Flash-Array liegen — das Log verdient seinen eigenen Storage.
Autogrowth: Der stille Performance-Killer
Autogrowth ist eine SQL-Server-Schutzfunktion: Wenn eine Datenbankdatei voll ist, wächst sie automatisch um einen konfigurierten Betrag. Das klingt harmlos. Es ist es nicht.
Das Problem: Während Autogrowth ausgeführt wird, ist die betroffene Datei für neue Zuweisungen gesperrt. Bei kleinen Wachstumsschritten (der Default ist 10 % — oder schlimmer: 1 MB bei älteren Installationen) wächst die Datei häufig, und jedes Mal gibt es einen kurzen Stall. Hundert Stalls pro Tag sind kein theoretisches Szenario.
|
Praxisbeispiel: Sparfuchs & Partner: 847 Autogrowth-Events in 120 Minuten |
|---|
|
Bei der Analyse von BUCHSQL01 (Kapitel 33) fanden wir im SQL Server Error Log 847 Autogrowth-Events in einem Zeitraum von 120 Minuten. Wachstumsschritt: 1 MB. Ohne Instant File Initialization (IFI). Das bedeutet: Alle 8,5 Sekunden eine IO-Blockierung, weil der Server die neue Seite erst nullen musste. Auf einer Spindel mit 312 ms p95-Write-Latenz. Jedes einzelne Autogrowth-Event kostete mehrere Sekunden. Die Symptome: Alle paar Minuten Timeouts in der Anwendung. Ursache: Eine 1-MB-Autogrowth-Einstellung aus dem Jahr 2008, die niemand je geändert hatte. |
Richtige Autogrowth-Konfiguration
Die Lösung ist einfach: Datenbankdateien vorab auf die erwartete Größe vorallokieren (Pre-Allocation) und Autogrowth als Sicherheitsnetz konfigurieren — mit vernünftigen Schrittgrößen:
|
Hinweis: Prozentales Wachstum ist fast immer falsch |
|---|
|
Der Standard-Autogrowth-Wert von 10 % klingt vernünftig — und ist es für eine 100-MB-Datenbank. Für eine 500-GB-Datenbank bedeutet 10 % ein Wachstum von 50 GB auf einmal. Das dauert (ohne IFI): mehrere Minuten. Immer feste Byte-Werte konfigurieren. |
Instant File Initialization: Fünf Minuten Arbeit, spürbare Wirkung
Wenn SQL Server eine neue Datendatei anlegt oder eine Datei vergrößert, nullt Windows den neuen Speicherbereich aus — Sektor für Sektor. Das ist ein Windows-Sicherheitsmerkmal (kein Lesen von fremden Daten aus dem Speicherplatz des vorherigen Benutzers). Es dauert messbar: Bei einer 10-GB-Datei auf einem HDD kann das mehrere Minuten in Anspruch nehmen.
Instant File Initialization (IFI) umgeht dieses Nullen für Datendateien (nicht für das Log!): Das SQL Server-Dienstkonto bekommt die Windows-Berechtigung SE_MANAGE_VOLUME_NAME, und danach werden neue Datendateien sofort als "verfügbar" markiert, ohne vorheriges Nullen. Das Ergebnis: Autogrowth dauert Millisekunden statt Minuten. Datenbank-Restores werden deutlich schneller.
-- IFI-Status prüfen: Ist es aktiv?
-- Erscheint "Instant File Initialization enabled" in der Output-Spalte,
-- ist IFI aktiv — der beste Zustand.
SELECT instant_file_initialization_enabled
FROM sys.dm_server_services
WHERE servicename LIKE 'SQL Server (%';
-- Alternativ: Im SQL Server Error Log prüfen
-- Beim Start meldet SQL Server: "Database Instant File Initialization: enabled."
-- oder: "Database Instant File Initialization: disabled."
EXEC xp_readerrorlog 0, 1, 'Instant File Initialization';
IFI aktivieren: SQL Server Configuration Manager öffnen, Dienst-Account ermitteln. Dann in der lokalen Sicherheitsrichtlinie (secpol.msc) unter "Lokale Richtlinien → Zuweisen von Benutzerrechten" die Berechtigung "Durchführen von Volumewartungsaufgaben" (SE_MANAGE_VOLUME_NAME) hinzufügen. SQL Server-Dienst neu starten. Fertig. Aufwand: fünf Minuten. Wirkung: Jede zukünftige Datei-Allokation und jeder Restore läuft schneller.
|
Warnung: IFI gilt nicht für das Transaktionslog |
|---|
|
Das Transaktionslog wird immer mit Nullen vorbelegt — auch mit IFI. Das ist absichtlich: Das Log enthält sensible Transaktionsdaten, die nicht aus altem Speicher wiederhergestellt werden dürfen. Log-Vergrößerungen sind deshalb immer langsamer als Datei-Vergrößerungen mit IFI. |
VLF-Explosion: Wenn das Transaktionslog zur Falle wird
Das SQL Server Transaktionslog ist intern in Virtual Log Files (VLFs) unterteilt. SQL Server schreibt sequenziell von einem VLF zum nächsten, dreht sich im Kreis, und verwendet inaktive VLFs wieder, wenn sie durch Log-Backup oder Checkpoint freigegeben wurden. Das ist das normale Verhalten. Das Problem entsteht, wenn zu viele VLFs entstehen.
VLFs entstehen bei jeder Log-Vergrößerung. Wächst das Log in vielen kleinen Schritten, entstehen viele kleine VLFs. SQL Server muss beim Datenbankstart alle VLFs durchgehen, beim Backup alle aktiven VLFs scannen, und beim Recovery alle relevanten VLFs lesen. Mit 48.312 VLFs — wie bei Sparfuchs & Partner (Kapitel 33) — dauert das Datenbankstart messbar länger und Log-Backups werden ineffizient.
-- VLF-Anzahl pro Datenbank ermitteln
-- Alles über 1.000 VLFs sollte man sich anschauen.
-- Alles über 10.000 ist ein Problem. Über 50.000: Sofortmaßnahmen.
SELECT
DB_NAME(database_id) AS Datenbank,
COUNT(*) AS VLF_Anzahl,
SUM(vlf_size_mb) AS Log_Groesse_MB
FROM sys.dm_db_log_info(NULL) -- NULL = alle Datenbanken
GROUP BY database_id
ORDER BY VLF_Anzahl DESC;
-- Detailansicht für eine spezifische Datenbank
-- vlf_status = 2: aktiv (noch nicht überschreibbar)
-- vlf_status = 0: inaktiv (kann wiederverwendet werden)
SELECT
vlf_begin_offset,
vlf_size_mb,
vlf_sequence_number,
vlf_status,
vlf_parity
FROM sys.dm_db_log_info(DB_ID('Produktion'));
VLF-Explosion beheben
Zu viele VLFs lassen sich beheben — aber nur mit etwas Geduld und dem richtigen Vorgehen:
|
Hintergrund: Wie viele VLFs sind "normal"? |
|---|
|
Microsoft empfiehlt weniger als 50 VLFs als Richtlinie, was in der Praxis für viele Datenbanken zu niedrig ist. Realistische Grenzwerte: Unter 500 VLFs: kein Problem. 500–2.000: überwachen. 2.000–10.000: shrink und reorg einplanen. Über 10.000: umgehend handeln. Die Anzahl optimaler VLFs hängt von der Log-Größe ab — eine 100-GB-Log-Datei mit 200 VLFs à 500 MB ist ideal. |
DiskSpd: Storage tatsächlich messen
Bevor du Entscheidungen über Storage-Konfiguration triffst, miss die tatsächliche Performance. DiskSpd ist das offizielle Microsoft-Werkzeug für Storage-Benchmarks — kostenlos, präzise, und in der Lage, genau die IO-Muster zu simulieren, die SQL Server produziert.
# DiskSpd - SQL Server OLTP-Simulation (zufälliger 8-KB-Read)
# -b8K: Blockgröße 8 KB (SQL Server-Seitengröße)
# -d60: 60 Sekunden Testlaufzeit
# -o4: 4 ausstehende IOs pro Thread (Queue Depth)
# -t4: 4 parallele Threads
# -r: zufällige IO-Verteilung (OLTP-typisch)
# -W15: 15 Sekunden Warm-up (werden nicht gemessen)
# -L: Latenz-Statistiken ausgeben (wichtig!)
diskspd.exe -b8K -d60 -o4 -t4 -r -W15 -L D:\testfile_10GB.dat
# SQL Server Log-Simulation (sequenzieller Write, 512-KB-Blöcke)
# -b512K: Log-ähnliche Schreibgröße
# -w100: 100% Writes
# -s: sequenziell (nicht zufällig)
# -L: Latenzen anzeigen — das ist was zählt
diskspd.exe -b512K -d60 -o4 -t2 -w100 -s -W15 -L L:\testfile_log.dat
# Testdatei anlegen (10 GB)
# DiskSpd kann das selbst: Einfach Dateipfad angeben,
# der nicht existiert — DiskSpd legt ihn an.
Die wichtigsten Kennzahlen in der DiskSpd-Ausgabe: "avg." in der Latenz-Sektion (Durchschnitt), "50th" (Median), "90th", "95th", "99th" (Percentilen) und "99.99th" (worst case). Der Vergleich mit den Grenzwerten aus der Tabelle oben zeigt sofort, ob der Storage die SQL Server-Anforderungen erfüllt.
|
Tipp: DiskSpd vor der Produktionsinstallation ausführen |
|---|
|
Storage-Tests gehören zur Pre-Deployment-Checkliste: bevor SQL Server installiert wird, DiskSpd auf allen Storage-Pfaden ausführen und die Ergebnisse dokumentieren. Das ist die Baseline. Wenn sechs Monate später Performance-Probleme auftreten, kannst du vergleichen: War der Storage damals schon so langsam, oder hat sich etwas geändert? Ohne Baseline ist Performance-Analyse Rätselraten — wie in Kapitel 9 ausführlich beschrieben. |
SQL Server IO-DMVs: Das Latenz-Dashboard
SQL Server sammelt IO-Statistiken in der Dynamic Management View sys.dm_io_virtual_file_stats. Sie liefert kumulative Werte seit dem letzten Neustart — und damit die Grundlage für eine einfache, aber effektive IO-Latenz-Analyse.
-- IO-Latenz-Dashboard: Durchschnittliche Lese- und Schreiblatenzen
-- pro Datenbankdatei seit dem letzten SQL-Server-Start.
-- Werte in Millisekunden. Alles über 20ms (Data) / 5ms (Log) prüfen.
SELECT
DB_NAME(vfs.database_id) AS Datenbank,
mf.name AS Dateiname,
mf.physical_name AS Pfad,
mf.type_desc AS Dateityp,
vfs.io_stall_read_ms / NULLIF(vfs.num_of_reads, 0) AS Lese_Latenz_ms,
vfs.io_stall_write_ms / NULLIF(vfs.num_of_writes, 0) AS Schreib_Latenz_ms,
vfs.io_stall / NULLIF(vfs.num_of_reads + vfs.num_of_writes, 0)
AS Gesamt_Latenz_ms,
vfs.num_of_reads AS Anzahl_Reads,
vfs.num_of_writes AS Anzahl_Writes,
CAST(vfs.num_of_bytes_read / 1048576.0 AS DECIMAL(18,1)) AS Gelesen_MB,
CAST(vfs.num_of_bytes_written / 1048576.0 AS DECIMAL(18,1)) AS Geschrieben_MB
FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS vfs
JOIN sys.master_files AS mf
ON vfs.database_id = mf.database_id
AND vfs.file_id = mf.file_id
ORDER BY Gesamt_Latenz_ms DESC;
-- Delta-Abfrage: Latenzen über 60 Sekunden messen (genauer als kumulativ)
-- Erst Snapshot nehmen, 60 Sekunden warten, zweiten Snapshot nehmen,
-- Differenz berechnen. So bekommst du aktuelle Latenzen statt Lifetime-Werte.
Diese Abfrage liefert kumulative Durchschnittswerte. Das bedeutet: Wenn der Server vor drei Monaten eine Woche lang langsam war und danach wieder normal lief, sind die kumulativen Werte verzerrt. Für genaue aktuelle Messung: Zwei Snapshots mit 60 Sekunden Abstand nehmen und die Differenz berechnen. Das Prinzip des Delta-Messens wird in Kapitel 9 (Wait Statistics) ausführlich erklärt — es gilt für DMVs generell.
Diagnose: IO-Performance-Probleme erkennen und einordnen
Symptome
|
Hinweis: Symptome eines IO-Performance-Problems |
|---|
|
Folgendes deutet auf IO-Probleme hin: • Nutzer melden sporadisch langsame Abfragen — besonders bei großen Reads oder unter Last • PAGEIOLATCH_SH, PAGEIOLATCH_EX oder WRITELOG dominieren die Wait Statistics (Kapitel 9) • sys.dm_io_virtual_file_stats zeigt Latenzen über 20 ms (Data) oder 5 ms (Log) • SQL Server Error Log enthält Meldungen "SQL Server has encountered X occurrence(s) of I/O requests taking longer than 15 seconds" • Task-Manager oder Performance Monitor zeigen hohe Disk Queue Length (über 2 pro Disk = Problem) • Backup-Laufzeiten nehmen zu ohne Änderung der Datenbankgröße |
So misst du das
|
Hinweis: IO-Performance messen: Drei Ebenen |
|---|
|
Ebene 1 — SQL Server intern (sofort): SELECT … FROM sys.dm_io_virtual_file_stats — Abfrage oben. Gibt durchschnittliche Latenzen seit Neustart. Ebene 2 — Windows Performance Monitor: Counters: "PhysicalDisk\Avg. Disk sec/Read", "PhysicalDisk\Avg. Disk sec/Write", "PhysicalDisk\Current Disk Queue Length". Schwellenwert Queue Length > 2. Ebene 3 — DiskSpd Benchmark: Synthetischer Last-Test mit SQL-Server-typischen IO-Mustern (8 KB random read, 512 KB sequential write). Liefert Percentil-Latenzen — aussagekräftiger als Durchschnitte. |
Typische Fehlinterpretationen
|
Warnung: Fehlinterpretationen bei IO-Diagnose |
|---|
|
1. "Hohe Disk-Aktivität ist schlecht" — Nein. Hohe Disk-Aktivität mit niedrigen Latenzen ist gut. Erst, wenn Latenzen steigen, wird Disk-Aktivität zum Problem. 2. "Backup-IO stört nicht" — Doch. Ein Backup, das mit hohem Durchsatz läuft, konkurriert mit produktivem IO um Queue-Slots. Backup-Window planen oder Backup-Drosselung nutzen. 3. "NVMe ist immer schnell" — Im Durchschnitt ja. Aber p99-Latenzen variieren stark. Günstige Consumer-NVMe-Drives können unter Last dramatisch einbrechen (Thermal Throttling, Cache-Sättigung). 4. "Kumulierte DMV-Werte zeigen die aktuelle Situation" — Nein. Immer Delta-Messungen verwenden für aktuelle Latenzen. Kumulierte Werte sind durch Lastspitzen der Vergangenheit verzerrt. |
Erste Gegenmaßnahmen
|
Tipp: Sofortmaßnahmen bei IO-Problemen |
|---|
|
1. Autogrowth prüfen: Wächst eine Datei gerade? DBCC SQLPERF(LOGSPACE) und Error Log prüfen. 2. Backup läuft gerade? sys.dm_exec_requests nach BACKUP DATABASE oder RESTORE DATABASE filtern. Falls ja: MAXTRANSFERSIZE erhöhen oder Backup in Nebenzeiten verschieben. 3. IO-Last identifizieren: sys.dm_exec_requests JOINen mit sys.dm_io_virtual_file_stats-Deltas — welche Session produziert gerade die meisten IOs? 4. RAID-Controller-Status prüfen: BBU-Status laut Controller-Management-Tool. Write-Through statt Write-Back? 5. Wait Statistics: PAGEIOLATCH-Anteil an allen Waits (Kapitel 9). Über 30%? Storage-Problem fast sicher. |
Zusammenfassung
Storage ist der häufigste Performance-Killer für SQL Server — und gleichzeitig die am häufigsten unterschätzte Komponente. Die wichtigsten Erkenntnisse dieses Kapitels:
Ein funktionierendes Storage-Setup ist die Grundvoraussetzung für alles, was danach kommt. Query-Tuning auf langsamen Platten ist wie Sportwagen-Tuning auf Feldwegen. Die Performance-Gewinne sind real, aber begrenzt.
Im nächsten Kapitel verlassen wir die physische Hardware und schauen uns an, was passiert, wenn SQL Server in einer virtuellen Maschine läuft. Virtualisierung ist heute Standard — aber sie bringt eine eigene Klasse von Performance-Problemen mit sich, von Memory Ballooning bis vNUMA-Konfigurationsfehler. Alles in Kapitel 3: Virtualisierung.
Kapitel 3
