SQL Server hält Daten- und Indexseiten im Arbeitsspeicher (Buffer Pool), um physische Lesevorgänge zu vermeiden. Je mehr Seiten im Cache liegen, desto schneller sind Abfragen. Doch wie finden Sie heraus, welche Datenbanken oder Tabellen gerade den Speicher belegen? Und wann sollten Sie den Cache leeren – etwa für Performancetests? Genau hier kommen sys.dm_os_buffer_descriptors, DBCC FREEPROCCACHE und DBCC DROPCLEANBUFFERS ins Spiel.
🎯 Lernziele: Buffer Pool-Auslastung analysieren, kalte und warme Seiten unterscheiden, Cache-Befehle sicher anwenden.
Diese dynamische Verwaltungssicht (DMV) liefert für jede einzelne Seite im Buffer Pool eine Zeile. Sie sehen, welche Datenbank, welches Objekt (Tabelle/Index) und welcher Seitentyp im Speicher ist – inklusive Status (z. B. dirty = geändert, aber noch nicht auf Platte geschrieben).
SELECT
COUNT(*) AS TotalPages,
COUNT(*) * 8 / 1024 AS BufferPoolSizeMB
FROM sys.dm_os_buffer_descriptors;
SELECT
DB_NAME(database_id) AS DatabaseName,
COUNT(*) AS CachedPages,
COUNT(*) * 8 / 1024 AS CachedSizeMB
FROM sys.dm_os_buffer_descriptors
GROUP BY database_id
ORDER BY CachedPages DESC;
Noch detaillierter: Welche Tabellen oder Indizes belegen den Speicher?
SELECT
DB_NAME(b.database_id) AS DatabaseName,
OBJECT_NAME(p.object_id, b.database_id) AS ObjectName,
i.name AS IndexName,
COUNT(*) AS PagesInMemory,
COUNT(*) * 8 / 1024 AS SizeInMemoryMB
FROM sys.dm_os_buffer_descriptors b
JOIN sys.allocation_units au ON b.allocation_unit_id = au.allocation_unit_id
JOIN sys.partitions p ON au.container_id = p.hobt_id
LEFT JOIN sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id
WHERE b.database_id = DB_ID('DeineDatenbank')
AND b.page_type IN ('DATA_PAGE', 'INDEX_PAGE')
GROUP BY b.database_id, p.object_id, i.name
ORDER BY PagesInMemory DESC;
💡 Praxistipp: Mit page_type können Sie gezielt nach Datenseiten, Indexseiten oder LOB-Seiten filtern. Auch "dirty" Seiten erkennen Sie über is_modified = 1.
Dieser Befehl entfernt alle sauberen Seiten aus dem Buffer Pool. "Sauber" bedeutet, dass sie nicht mehr geändert wurden (keine ausstehenden Schreibvorgänge). Dirty Pages werden nicht gelöscht – sie müssen zuerst von der Checkpoint- oder Lazywriter-Prozess auf die Platte geschrieben werden.
🛑 Wichtiger Warnhinweis: In einer Produktionsumgebung führt DBCC DROPCLEANBUFFERS zu einem massiven Leistungseinbruch, weil der Cache „kalt“ wird. Jede Abfrage muss von der Festplatte/SSD lesen. Verwenden Sie diesen Befehl nur auf Entwicklungs- oder Testsystemen – und niemals während der regulären Betriebszeit.
📌 Typischer Anwendungsfall: Sie möchten die Performance einer Abfrage ohne Einfluss bereits gecachter Daten messen („Kalter Cache“-Test) oder vergleichen, wie ein Index die Lesevorgänge verbessert. Dazu führen Sie DBCC DROPCLEANBUFFERS vor jeder Testausführung aus.
Der Plan Cache (Procedure Cache) speichert kompilierte Ausführungspläne für Abfragen, gespeicherte Prozeduren und Funktionen. DBCC FREEPROCCACHE löscht alle Pläne aus dem Cache – SQL Server muss danach jede Abfrage neu kompilieren.
DBCC FREEPROCCACHE;
DBCC FREEPROCCACHE (DB_ID('DeineDatenbank'));
DBCC FREEPROCCACHE (0x06000500123ABCDE);
📉 Wann sinnvoll? Nach Änderungen an Tabellenschemata, Indexänderungen oder wenn ein einzelner „schlechter“ Plan den Cache verstopft. In der Praxis löschen Administratoren selten den gesamten Procedure Cache – das führt zu einem „Kompilierungs-Sturm“ und hoher CPU-Last. Besser gezielt einzelne Pläne entfernen.
🔍 Vorher analysieren: Nutzen Sie sys.dm_exec_query_stats und sys.dm_exec_sql_text, um problematische Pläne zu identifizieren, bevor Sie sie löschen.
In einer Testumgebung möchten Sie oft einen „kalten“ Zustand mit leerem Daten- und Plancache simulieren. Dann verwenden Sie beide Befehle nacheinander:
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;
🧪 Typisches Szenario: Sie möchten die Dauer einer großen Report-Abfrage unter „schlimmsten“ Bedingungen messen (keine vorgewärmten Daten). Dazu setzen Sie den Cache zurück und führen die Abfrage mehrfach aus, wobei Sie die Latenz nach dem ersten Durchlauf vergleichen.
🚨 Achtung: Nach einem kompletten Cache-Reset steigt die CPU-Auslastung massiv an, weil jede Abfrage neu kompiliert wird und alle Daten von der Platte kommen. Das kann einen Produktivserver für Minuten oder Stunden lahmlegen. Verwenden Sie diese Befehle daher niemals auf einem System, auf das Benutzer zugreifen.
Statt den Cache einfach zu löschen, sollten Sie zuerst analysieren, ob überhaupt ein Problem vorliegt. Dazu dienen folgende Performance-Indikatoren:
SELECT
CAST(cntr_value AS FLOAT) AS BufferHitRate
FROM sys.dm_os_performance_counters
WHERE object_name LIKE '%Buffer Manager%'
AND counter_name = 'Buffer cache hit ratio';
SELECT
CAST(cntr_value AS FLOAT) AS PlanHitRatio
FROM sys.dm_os_performance_counters
WHERE object_name LIKE '%Plan Cache%'
AND counter_name = 'Cache Hit Ratio'
AND instance_name = 'SQL Plans';
SELECT
total_physical_memory_kb / 1024 AS TotalRAM_MB,
available_physical_memory_kb / 1024 AS AvailableRAM_MB
FROM sys.dm_os_sys_memory;
💡 Empfehlung: Wenn die Buffer-Hitrate unter 90 % fällt, ist Ihr Server entweder überlastet oder Sie haben zu wenig Arbeitsspeicher für die Datenbank dimensioniert. Dann hilft es nicht, den Cache zu leeren – Sie müssen mehr RAM bereitstellen oder Abfragen optimieren.
- Niemals in Produktion – Es sei denn, Sie haben ein explizites Wartungsfenster und wissen genau, was Sie tun.
- Vor dem Reset: Aktuelle Cache-Inhalte dokumentieren (z. B. Top-Tabellen im Buffer Pool, teure Pläne).
- Nach dem Reset: Den Server beobachten (CPU, Lesevorgänge, Abfragewartezeiten).
- Geplante Tests: Verwenden Sie
DBCC DROPCLEANBUFFERS und DBCC FREEPROCCACHE nur in isolierten Testumgebungen.
- Gezieltes Löschen: Statt den gesamten Plan-Cache zu leeren, entfernen Sie einzelne Pläne über
sys.dm_exec_query_stats und DBCC FREEPROCCACHE(plan_handle).
- Automatisierung: Bauen Sie keine regelmäßigen Jobs, die den Cache zurücksetzen – das wäre kontraproduktiv.
🧠 Merksatz: Der Buffer Pool und Plan Cache sind Ihre Freunde – sie beschleunigen Ihr System. Leeren Sie sie nur, wenn Sie einen wirklich guten Grund haben (z. B. reproduzierbare Performance-Messungen).
Angenommen, Sie vermuten, dass eine bestimmte Datenbank zu viel Speicher belegt und andere ausbremsen. Mit einem einfachen Skript ermitteln Sie die genaue Verteilung:
SELECT
DB_NAME(database_id) AS DatabaseName,
COUNT(*) AS PageCount,
CAST(COUNT(*) * 8 / 1024.0 AS DECIMAL(10,2)) AS SizeInMB,
SUM(CASE WHEN is_modified = 1 THEN 1 ELSE 0 END) AS DirtyPages
FROM sys.dm_os_buffer_descriptors
GROUP BY database_id
ORDER BY SizeInMB DESC;
📈 Interpretation: Sieht eine Datenbank ungewöhnlich groß im Buffer Pool aus, prüfen Sie, ob dort kürzlich große Tabellen-Scans stattgefunden haben. Mit gezielten Indexanpassungen oder Abfrageoptimierungen reduzieren Sie die Cache-Belastung, ohne den gesamten Puffer zu leeren.
- ❌ „DBCC DROPCLEANBUFFERS gibt Speicher an das Betriebssystem zurück“ – Nein, der SQL Server behält die reservierten Puffer, sie werden nur mit leeren Seiten überschrieben. Der Speicher wird nicht freigegeben.
- ❌ „Nach FREEPROCCACHE laufen alle Abfragen schneller“ – Das Gegenteil ist oft der Fall: Neukompilierungen kosten Zeit und CPU.
- ❌ „Ich leere den Cache regelmäßig als Wartungsjob“ – Das ist ein schwerer Fehler, der die Performance dauerhaft verschlechtert.
- ❌ „sys.dm_os_buffer_descriptors zeigt nur Datenbankseiten an“ – Ja, aber auch Systemseiten (z. B. von tempdb) sind enthalten – filtern Sie ggf. nach database_id > 4.
🚀 Fazit für den Alltag: Nutzen Sie die DMV sys.dm_os_buffer_descriptors, um den Cache zu verstehen. Greifen Sie zu DBCC DROPCLEANBUFFERS und DBCC FREEPROCCACHE nur in kontrollierten Tests. In der Produktion sind diese Befehle in 99 % der Fälle nicht hilfreich – im Gegenteil, sie schaden.