Wissen

Praxis-Artikel und Buchkapitel zu SQL-Performance, Sicherheit und Hochverfügbarkeit – alle frei verfügbar.

Beratung

Festpreis-Analyse mit Bericht und Handlungsempfehlung – oder strategische Begleitung bei Architektur, Migration und Hochverfügbarkeit.

Fachbücher

Die fünfbändige Reihe „Ulis SQL-Bibliothek“ – Band 1 verfügbar. Leseprobe herunterladen!

Tools

UB.SimSQL: SQL-Server-Lastsimulator mit regelbasierten Konfigurationsempfehlungen. Lokal, ohne Cloud, ohne Abo.

Schulungen

Online-Workshops zu Performance, Sicherheit und Entwicklung – kompakt, hands-on, ohne MOC-Folienschlacht.

SQL Server Resource Governor im Detail

Workload-Steuerung mit Resource Pools, Workload Groups und Classifier Function

Der Resource Governor im SQL Server: Ressourcenfresser an die Leine

Wie Sie mit Resource Pools, Workload Groups und einer Classifier Function dafür sorgen, dass der Monatsexport nicht die Produktion lahmlegt

Jede produktive SQL-Server-Instanz kennt das Phänomen des lauten Nachbarn: Alles läuft rund, bis jemand den großen Export anwirft, das Controlling seine Excel-Abfrage von der Kette lässt oder ein Wartungsjob zur Unzeit startet. Plötzlich stehen die Anwender der eigentlichen Fachanwendung im Stau — und der Admin darf erklären, warum die Warenwirtschaft „mal wieder langsam" ist. Der Resource Governor ist die Antwort des SQL Servers auf genau dieses Problem: Er verteilt CPU, Arbeitsspeicher und I/O kontrolliert auf konkurrierende Workloads, statt alle in denselben Topf greifen zu lassen. In diesem Artikel schauen wir uns an, wie das Feature aufgebaut ist, wo die Fallstricke liegen und wie zwei reale Projekte damit ihre Performance-Probleme gelöst haben.

FAKTENKASTEN — SQL Server Resource Governor

Der Resource Governor ist seit SQL Server 2008 Bestandteil des Produkts und steuert die Verteilung von CPU, Arbeitsspeicher und physischem I/O zwischen Workloads einer Instanz.

Das Feature erfordert die Enterprise Edition (bzw. Developer/Evaluation Edition); in der Standard Edition und in Express ist es nicht verfügbar.

Die drei Kernkomponenten sind Resource Pools, Workload Groups und die Classifier Function (eine skalare benutzerdefinierte Funktion in der master-Datenbank).

CAP_CPU_PERCENT (hartes CPU-Limit) ist seit SQL Server 2012 verfügbar, die I/O-Steuerung über MIN_IOPS_PER_VOLUME/MAX_IOPS_PER_VOLUME seit SQL Server 2014.

Konfigurationsänderungen werden erst mit ALTER RESOURCE GOVERNOR RECONFIGURE wirksam; die Klassifizierung erfolgt einmalig beim Verbindungsaufbau.

Stand: August 2026 · boddenberg.de

 

1. Wozu das Ganze? Das Problem der lauten Nachbarn

SQL Server ist von Haus aus ein Gleichmacher: Jede Session, die sich verbindet, darf sich grundsätzlich an denselben Ressourcen bedienen. Das ist fair — aber fair ist nicht immer klug. Die 200 Sachbearbeiter, die im ERP Aufträge buchen, sind für das Unternehmen schlicht wichtiger als der eine Export-Job, der einmal im Monat drei Stunden lang Daten für ein Drittsystem herausschaufelt. Ohne Steuerung gewinnt aber gern der Export: Er liest riesige Datenmengen, zieht sich fette Memory Grants, parallelisiert auf allen Kernen — und die Sachbearbeiter warten.

Die klassischen Auswege sind alle unbefriedigend: Den Export nachts laufen zu lassen scheitert oft an fachlichen Vorgaben oder an Zeitzonen. Eine zweite Instanz oder ein Reporting-Replikat kostet Lizenzen und Betriebsaufwand. Und dem Fachbereich zu erklären, er möge doch bitte „rücksichtsvoller abfragen", hat noch nie funktioniert. Der Resource Governor setzt eine Ebene tiefer an: Er lässt alle weiterarbeiten, teilt aber die Ressourcen nach Prioritäten zu. Der Export läuft weiter — nur eben gedrosselt, sodass die Anwendung nichts mehr davon merkt.

2. Die Architektur: drei Bausteine, klare Rollen

Das Konzept ist erfreulich übersichtlich. Es gibt genau drei Bausteine, und wenn Sie deren Rollen einmal verstanden haben, ist der Rest Handwerk.

Resource-Governor-Architektur: Sessions werden per Classifier Function Workload Groups und Resource Pools zugeordnet.

Skizze 1: Eingehende Sessions werden von der Classifier Function auf Workload Groups verteilt, die wiederum an Resource Pools hängen

Baustein

Aufgabe

Typische Einstellungen

Resource Pool

Der eigentliche Ressourcentopf: partitioniert CPU, Arbeitsspeicher und physisches I/O der Instanz.

MIN_CPU_PERCENT, MAX_CPU_PERCENT, CAP_CPU_PERCENT, MAX_MEMORY_PERCENT, MAX_IOPS_PER_VOLUME

Workload Group

Logischer Container für Sessions; hängt an genau einem Pool und regelt Verhalten auf Request-Ebene.

IMPORTANCE, MAX_DOP, REQUEST_MAX_MEMORY_GRANT_PERCENT, REQUEST_MEMORY_GRANT_TIMEOUT_SEC, GROUP_MAX_REQUESTS

Classifier Function

Der Türsteher: entscheidet bei jedem Login, in welche Workload Group die Session wandert.

Skalare UDF in master, ausgewertet werden z. B. SUSER_SNAME(), APP_NAME(), HOST_NAME(), IS_MEMBER()

 

Zwei Pools und zwei Groups existieren immer, ob Sie wollen oder nicht: internal ist für den SQL Server selbst reserviert — Lazy Writer, Checkpoints, interne Prozesse — und lässt sich weder begrenzen noch löschen. Das ist auch gut so, denn ein SQL Server, der sich selbst aushungert, hilft niemandem. default fängt alles auf, was die Classifier Function nicht ausdrücklich woanders hinschickt. Eigene Pools und Groups legen Sie zusätzlich an; bis zu 64 Resource Pools sind seit SQL Server 2012 möglich — in der Praxis kommen Sie mit drei bis fünf gut hin, und mehr als das sollte man sich auch gut überlegen.

MERKE

Weniger ist mehr: Jeder zusätzliche Pool mit MIN-Garantien reserviert Ressourcen, die anderen fehlen. Ein sauberes Design hat einen Pool für die geschützte Kernanwendung, einen für die Übeltäter — und den default für den Rest.

 

3. Was beim Login passiert

Die Klassifizierung ist ein einmaliger Vorgang beim Verbindungsaufbau. Nach der Authentifizierung ruft der SQL Server die hinterlegte Classifier Function auf; deren Rückgabewert — der Name einer Workload Group — bestimmt, wo die Session für ihre gesamte Lebensdauer einsortiert wird. Gibt die Funktion NULL oder einen unbekannten Namen zurück, landet die Session in der default-Group.

5-Schritte-Ablauf beim SQL-Server-Login: von Classifier-Ausführung über Group-Zuordnung bis zu Pool-Limits und Monitoring.

Skizze 2: Der Weg einer Session vom Login bis zur wirksamen Ressourcenbegrenzung

WARNBOX — Die Classifier Function ist Ihr Login-Nadelöhr

Die Funktion läuft bei jedem einzelnen Verbindungsaufbau — bei Connection-Pooling-Anwendungen also seltener, bei allem anderen ständig. Wer hier Tabellenzugriffe, Abfragen auf Konfigurationstabellen oder aufwendige Logik einbaut, verwandelt den Türsteher in einen Flaschenhals: Jeder Login wartet, bis die Funktion fertig ist.

Die Regel lautet: nur In-Memory-Funktionen wie SUSER_SNAME(), APP_NAME() oder IS_MEMBER(), simple Vergleiche, WITH SCHEMABINDING, fertig. Wenn Sie Lookup-Tabellen brauchen, gehören die als hartkodierte Logik in die Funktion oder in eine memory-optimized Table — nicht als klassischer Tabellenzugriff auf eine Benutzerdatenbank.

 

Wichtig für die Betriebspraxis: Eine bestehende Session wird nie nachträglich umklassifiziert. Ändern Sie die Konfiguration, gilt sie nur für neue Verbindungen. Bei Anwendungen mit Connection Pooling kann das bedeuten, dass alte Zuordnungen noch stundenlang weiterleben, bis der Pool seine Verbindungen erneuert — im Zweifel hilft ein kontrollierter Neustart des Anwendungsdienstes.

4. CPU, Memory, I/O: Was sich wie begrenzen lässt

Die Stellschrauben verteilen sich auf zwei Ebenen: Pool-Einstellungen begrenzen die physischen Ressourcen, Group-Einstellungen das Verhalten einzelner Requests. Die wichtigsten Parameter im Überblick:

Parameter

Ebene

Wirkung

Seit

MIN_CPU_PERCENT

Pool

Garantierter CPU-Anteil bei Konkurrenz — die Untergrenze, die niemand wegnehmen kann.

2008

MAX_CPU_PERCENT

Pool

Weiches CPU-Limit: greift nur bei Konkurrenz. Ist sonst nichts los, darf der Pool mehr nehmen.

2008

CAP_CPU_PERCENT

Pool

Hartes CPU-Limit: gilt immer, auch wenn die Instanz ansonsten Däumchen dreht.

2012

MAX_MEMORY_PERCENT

Pool

Deckelt den Query-Arbeitsspeicher (Memory Grants) des Pools — nicht den Buffer Pool!

2008

MIN_IOPS_PER_VOLUME / MAX_IOPS_PER_VOLUME

Pool

Begrenzung des physischen I/O je Volume — der Klassiker gegen Storage-fressende Exporte.

2014

IMPORTANCE

Group

Relative Gewichtung (LOW/MEDIUM/HIGH) bei der CPU-Zuteilung innerhalb desselben Pools.

2008

MAX_DOP

Group

Maximaler Parallelitätsgrad für Requests der Group — übersteuert die Serverkonfiguration.

2008

REQUEST_MAX_MEMORY_GRANT_PERCENT

Group

Wie viel vom Pool-Speicher darf ein einzelner Request als Grant bekommen.

2008

GROUP_MAX_REQUESTS

Group

Wie viele Requests der Group gleichzeitig laufen dürfen — der Rest wartet.

2008

 

Der mit Abstand am häufigsten missverstandene Punkt ist der Unterschied zwischen MAX_CPU_PERCENT und CAP_CPU_PERCENT. MAX ist ein Schönwetter-Limit: Es greift nur, wenn tatsächlich mehrere Pools um CPU konkurrieren. Nachts um drei, wenn sonst nichts läuft, darf der Export-Pool trotz MAX = 25 fröhlich 90 % CPU ziehen — was oft sogar erwünscht ist, denn dann ist er schneller fertig. Wer dagegen garantierte, jederzeit vorhersagbare Obergrenzen braucht (etwa für interne Verrechnung oder um Messwerte stabil zu halten), nimmt CAP.

Vergleich MAX_CPU_PERCENT vs. CAP_CPU_PERCENT: weiches Limit greift nur bei Konkurrenz, hartes Limit wirkt immer.

Skizze 3: MAX_CPU_PERCENT drosselt nur bei Konkurrenz — CAP_CPU_PERCENT deckelt immer

WARNBOX — Der Memory-Irrtum

MAX_MEMORY_PERCENT begrenzt nicht den Buffer Pool, sondern ausschließlich den Arbeitsspeicher für Query-Verarbeitung — also Memory Grants für Sorts, Hash Joins und Co. Wer glaubt, er könne damit verhindern, dass ein Export den Datencache der Anwendung verdrängt, wird enttäuscht: Gegen Buffer-Pool-Verdrängung durch große Scans hilft der Resource Governor nicht.

Was dagegen sehr wohl funktioniert: REQUEST_MAX_MEMORY_GRANT_PERCENT auf Group-Ebene verhindert, dass eine einzelne Monster-Query den Grant-Speicher leerräumt und alle anderen in RESOURCE_SEMAPHORE-Wartezustände zwingt. Das ist in der Praxis einer der wirksamsten Hebel überhaupt.

 

5. Konfiguration Schritt für Schritt

Die komplette Einrichtung für ein typisches Szenario — ein gedeckelter Pool für Export-Prozesse — sieht so aus:

USE master;

GO

— 1) Resource Pool: die physischen Grenzen

CREATE RESOURCE POOL Pool_Exporte

WITH ( MAX_CPU_PERCENT = 25,

CAP_CPU_PERCENT = 40,

MAX_MEMORY_PERCENT = 30,

MAX_IOPS_PER_VOLUME = 500 );

GO

— 2) Workload Group: das Verhalten der Requests

CREATE WORKLOAD GROUP WG_Exporte

WITH ( IMPORTANCE = LOW,

MAX_DOP = 2,

REQUEST_MAX_MEMORY_GRANT_PERCENT = 20 )

USING Pool_Exporte;

GO

— 3) Classifier Function: der Tuersteher

CREATE FUNCTION dbo.fn_RG_Classifier()

RETURNS sysname

WITH SCHEMABINDING

AS

BEGIN

DECLARE @wg sysname = N'default';

IF SUSER_SNAME() = N'DOMAIN\svc_export'

SET @wg = N'WG_Exporte';

RETURN @wg;

END;

GO

— 4) Funktion registrieren und scharf schalten

ALTER RESOURCE GOVERNOR

WITH (CLASSIFIER_FUNCTION = dbo.fn_RG_Classifier);

ALTER RESOURCE GOVERNOR RECONFIGURE;

GO

 

MERKE

Ohne ALTER RESOURCE GOVERNOR RECONFIGURE passiert exakt gar nichts — die Konfiguration liegt dann zwar in den Metadaten, ist aber nicht aktiv. Das ist der häufigste „Warum wirkt das nicht?"-Moment überhaupt. Ob die Laufzeitkonfiguration aktuell ist, verrät die Spalte is_reconfiguration_pending in sys.dm_resource_governor_configuration.

 

Vor dem Scharfschalten sollten Sie die Klassifizierungslogik testen — und zwar so, dass Sie sich nicht selbst aussperren. Bewährt hat sich ein zweistufiges Vorgehen: Die Funktion zunächst so bauen, dass sie ausschließlich einen einzelnen Test-Login klassifiziert und für alles andere default zurückgibt. Dann mit diesem Test-Login verbinden und die Zuordnung prüfen:

SELECT s.session_id, s.login_name, s.program_name,

wg.name AS workload_group, rp.name AS resource_pool

FROM sys.dm_exec_sessions s

JOIN sys.dm_resource_governor_workload_groups wg

ON s.group_id = wg.group_id

JOIN sys.dm_resource_governor_resource_pools rp

ON wg.pool_id = rp.pool_id

WHERE s.is_user_process = 1;

 

PRAXISBOX — Der Rettungsanker heißt DAC

Sollte die Classifier Function jemals so danebengehen, dass reguläre Logins hängen oder falsch einsortiert werden: Die Dedicated Admin Connection (DAC) wird grundsätzlich nicht klassifiziert und läuft immer in der internal-Group. Per sqlcmd -A kommen Sie also garantiert auf die Instanz und können mit ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = NULL) plus RECONFIGURE den Türsteher feuern. Diesen Befehl sollten Sie griffbereit haben, bevor Sie das erste Mal scharf schalten — nicht erst googeln, wenn es brennt.

 

6. Praxisbeispiel 1: Der Monatsexport und die HA-Falle

Ein Logistikunternehmen, zwei SQL-Server-Knoten in einer Availability Group, darauf die zentrale Fachanwendung mit einigen hundert gleichzeitigen Benutzern. Das Problem: An den ersten Werktagen jedes Monats laufen große Datenexporte für nachgelagerte Systeme — angestoßen von benannten Service-Accounts des Datenmanagement-Teams. In diesen Zeitfenstern brachen die Antwortzeiten der Anwendung regelmäßig ein; die Exporte lasen riesige Datenmengen, parallelisierten auf allen Kernen und dominierten das Storage.

Die Lösung war ein Lehrbuchfall für den Resource Governor: ein Pool Pool_Exporte mit CAP_CPU_PERCENT = 40 und MAX_IOPS_PER_VOLUME, dazu eine Workload Group mit IMPORTANCE = LOW und MAX_DOP = 2. Klassifiziert wurde über die Login-Namen der Export-Accounts — sauber, eindeutig, nicht manipulierbar. Ergebnis: Die Exporte dauerten statt gut zwei Stunden etwa dreieinhalb, was fachlich völlig egal war. Die Anwendung lief durchgehend stabil, die Beschwerden zum Monatsanfang verschwanden.

Die eigentliche Lektion kam beim ersten Failover-Test: Auf dem zweiten Knoten waren die Exporte plötzlich wieder ungebremst unterwegs. Der Grund ist so simpel wie fies — die gesamte Resource-Governor-Konfiguration inklusive Classifier Function lebt in der master-Datenbank, und die repliziert eine Availability Group nicht mit. Wer nur auf dem primären Knoten konfiguriert, hat nach dem Failover exakt gar nichts.

WARNBOX — Availability Groups: master reist nicht mit

Resource Pools, Workload Groups und die Classifier Function sind Instanzkonfiguration in master. In HA-Umgebungen (Availability Groups wie klassisches Log Shipping) muss die Konfiguration auf jedem Replikat identisch gepflegt werden — per Deployment-Skript, nicht per Hand.

Gehört zwingend dazu: ein Monitoring-Check, der die Konfiguration beider Knoten vergleicht. Bei dem beschriebenen Kunden läuft seitdem ein täglicher Abgleich der Pool- und Group-Definitionen über beide Replikate — Abweichung erzeugt ein Ticket. Klingt paranoid, hat aber seither zweimal einen vergessenen Knoten nach Konfigurationsänderungen gefangen.

 

7. Praxisbeispiel 2: Controlling-Excel gegen die Warenwirtschaft

Zweiter Fall, anderes Kaliber: ein mittelständisches Handelsunternehmen, Warenwirtschaft auf einer SQL-Server-Instanz, und jeden Tag gegen Mittag wurde das System zäh. Die Analyse zeigte ein klassisches Muster — aus dem Controlling kamen Power-Query- und Excel-Abfragen direkt auf die Produktionsdatenbank, mit gigantischen Memory Grants und voller Parallelisierung. Eine einzige dieser Abfragen reservierte zeitweise mehr Query-Speicher als die gesamte Warenwirtschaft zusammen; andere Requests warteten im RESOURCE_SEMAPHORE.

Erster Wurf der Klassifizierung: über APP_NAME(), denn die Office-Datenverbindungen melden sich mit erkennbaren Programmnamen an. Funktionierte auf Anhieb — hat aber einen Haken, der im Review zu Recht auf den Tisch kam: Der Application Name ist ein Feld im Connection String, das jeder Client frei setzen kann. Wer sich als Warenwirtschaft ausgibt, umgeht die Bremse. Für ein Komfort-Feature ist das akzeptabel, als belastbare Grenze nicht. Die finale Classifier Function kombinierte deshalb beides: Mitgliedschaft in einer eigens angelegten AD-Gruppe der Controlling-Benutzer (geprüft per IS_MEMBER()) als primäres Kriterium, APP_NAME() nur noch als Zusatzindiz.

Die Limits selbst waren bewusst milde: REQUEST_MAX_MEMORY_GRANT_PERCENT = 15, MAX_DOP = 2, kein CPU-Cap. Der Effekt war trotzdem durchschlagend, weil das eigentliche Problem nie die CPU war, sondern die Memory Grants. Die Warenwirtschaft lief ab dem ersten Tag stabil; im Controlling dauerte die größte Auswertung statt fünf nun acht Minuten — was dort schlicht niemandem auffiel. Der schönste Satz aus dem Abschlussgespräch: „Wir dachten, ihr hättet neue Hardware eingebaut."

PRAXISBOX — Weniger drosseln, gezielter drosseln

In beiden Projekten war der wirksamste Hebel nicht das CPU-Limit, sondern Memory Grant und MAX_DOP auf Group-Ebene. CPU-Deckel sind das, woran alle zuerst denken — Grant-Begrenzung ist das, was die Blockaden tatsächlich löst. Erst messen (Wait Stats!), dann deckeln: Wer RESOURCE_SEMAPHORE-Waits sieht, hat ein Grant-Problem, kein CPU-Problem.

 

8. Betrieb und Monitoring

Ein Resource Governor ohne Monitoring ist ein Blindflug — Sie wollen wissen, ob die Limits greifen, ob Pools am Anschlag laufen und ob die Klassifizierung das tut, was sie soll. Die wichtigsten Anlaufstellen:

Sicht / Werkzeug

Was Sie dort sehen

sys.dm_resource_governor_resource_pools

Laufzeitstatistiken je Pool: CPU-Verbrauch, Speichernutzung, I/O — die zentrale Betriebssicht.

sys.dm_resource_governor_workload_groups

Statistiken je Group: aktive Requests, Queued Requests, durchschnittliche CPU-Zeit, Grant-Timeouts.

sys.dm_exec_sessions (Spalte group_id)

Welche Session in welcher Group gelandet ist — der Klassifizierungs-Check.

sys.dm_resource_governor_configuration

Aktive Classifier Function und ob eine Rekonfiguration aussteht (is_reconfiguration_pending).

Perfmon: SQLServer:Resource Pool Stats / Workload Group Stats

Zeitreihen für CPU, Memory Grants und Co. je Pool/Group — ideal für Baselines und Alarme.

sys.resource_governor_resource_pools u. a. (Katalogsichten)

Die konfigurierten Soll-Werte — Grundlage für den Konfigurationsabgleich zwischen HA-Knoten.

 

MERKE

Vor jeder Limitierung eine Baseline ziehen: mindestens eine Woche Pool-/Group-Statistiken sammeln, bevor Grenzen gesetzt werden. Limits ohne Baseline sind geraten — und geratene Limits sind entweder wirkungslos oder würgen die Falschen ab.

 

9. Grenzen: Was der Resource Governor nicht kann

So nützlich das Feature ist — es lohnt sich, die Grenzen klar zu benennen, bevor falsche Erwartungen entstehen:

  • Keine Steuerung pro Datenbank oder pro Query. Klassifiziert wird die Session, nicht die einzelne Abfrage. Eine Session, die brav anfängt und dann eine Monster-Query absetzt, bleibt in ihrer Group.
  • Kein Schutz des Buffer Pools. Die Memory-Limits betreffen Query-Arbeitsspeicher, nicht den Datencache. Cache-Verdrängung durch große Scans verhindert der Resource Governor nicht.
  • Kein Netzwerk, kein tempdb-Kontingent. Netzwerkbandbreite und tempdb-Platzverbrauch lassen sich nicht über Pools begrenzen.
  • Kein Ersatz für Query-Tuning. Eine schlechte Abfrage bleibt schlecht — sie ärgert nur weniger Leute gleichzeitig. Fehlende Indizes, veraltete Statistiken und krumme Abfragemuster löst man weiterhin an der Wurzel.
  • Edition und Plattform. Enterprise Edition vorausgesetzt; in Azure SQL Database ist das Feature nicht für eigene Konfiguration verfügbar (dort nutzt es die Plattform intern), in Azure SQL Managed Instance dagegen schon.
  •  

    Richtig eingeordnet ist der Resource Governor damit kein Performance-Wundermittel, sondern ein Priorisierungswerkzeug: Er sorgt dafür, dass die wichtigen Workloads die Ressourcen bekommen, die ihnen zustehen — und dass die unwichtigen ihre Arbeit trotzdem erledigen dürfen, nur eben in der Holzklasse.

    Häufig gestellte Fragen (FAQ)

    Welche SQL-Server-Edition brauche ich für den Resource Governor?

    Die Enterprise Edition. Developer und Evaluation Edition können das Feature ebenfalls (für Test und Entwicklung), die Standard Edition und Express dagegen nicht. Das ist in Projekten regelmäßig der erste Punkt, an dem die schöne Idee scheitert — die Editionsfrage gehört deshalb ganz an den Anfang jeder Planung.

    Seit welcher Version gibt es welche Funktionen?

    Das Grundgerüst — Pools, Groups, Classifier, CPU- und Memory-Steuerung — existiert seit SQL Server 2008. Mit SQL Server 2012 kamen CAP_CPU_PERCENT (hartes CPU-Limit), Affinity-Steuerung auf Pool-Ebene und die Erhöhung auf 64 Pools hinzu. SQL Server 2014 ergänzte die I/O-Steuerung über MIN_IOPS_PER_VOLUME und MAX_IOPS_PER_VOLUME. Seither ist das Feature funktional weitgehend stabil geblieben.

    Funktioniert der Resource Governor in Azure?

    Differenziert: In Azure SQL Database steht er nicht zur eigenen Konfiguration bereit — Microsoft nutzt ihn dort intern zur Steuerung der Service-Tiers. In Azure SQL Managed Instance können Sie ihn wie gewohnt konfigurieren. Auf SQL Servern in Azure-VMs gilt schlicht die normale Editionsregel.

    Kann ich damit eine bestimmte Datenbank begrenzen?

    Nicht direkt — klassifiziert werden Sessions, nicht Datenbanken. Indirekt geht es aber oft trotzdem: Wenn eine Anwendung „ihre" Datenbank über dedizierte Logins nutzt, klassifizieren Sie einfach diese Logins. Alternativ lässt sich in der Classifier Function ORIGINAL_DB_NAME() auswerten — das greift allerdings nur, wenn die Datenbank im Connection String angegeben wird, und ist entsprechend umgehbar.

    Was passiert mit Sessions, die die Classifier Function nicht zuordnet?

    Sie landen in der default-Group im default-Pool. Das ist ein bewusst gutmütiges Verhalten: Ein NULL-Rückgabewert, ein Tippfehler im Group-Namen oder ein Fehler in der Funktion sperren niemanden aus, sondern führen nur zur Standardzuordnung.

    Wirken Konfigurationsänderungen auf bestehende Sessions?

    Nein und ja. Die Klassifizierung einer Session steht mit dem Login fest und ändert sich nie mehr. Geänderte Limits eines Pools oder einer Group wirken nach dem RECONFIGURE dagegen auch auf Sessions, die dieser Group bereits zugeordnet sind — nur die Zuordnung selbst bleibt fix. Wer Sessions in eine andere Group bringen will, braucht einen Reconnect.

    Ich habe mich mit der Classifier Function ausgesperrt — was nun?

    Ruhe bewahren und die Dedicated Admin Connection nutzen: sqlcmd -A (oder ADMIN:Servername im SSMS-Verbindungsdialog, dort nur mit dem Abfragefenster). Die DAC wird nicht klassifiziert und funktioniert daher immer. Darüber setzen Sie ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = NULL); gefolgt von ALTER RESOURCE GOVERNOR RECONFIGURE; ab — damit ist der Türsteher entlassen und alle neuen Sessions laufen wieder in default.

    Wie verhält sich der Resource Governor in Availability Groups?

    Er weiß schlicht nichts von ihnen. Die gesamte Konfiguration liegt in der master-Datenbank und ist damit reine Instanzkonfiguration — sie wird von der Availability Group nicht repliziert. Sie müssen die Konfiguration auf jedem Replikat identisch pflegen, idealerweise skriptbasiert über eine Deployment-Pipeline, und den Gleichstand regelmäßig automatisiert prüfen. Wer das nicht tut, verliert seine Limits beim ersten Failover (siehe Praxisbeispiel 1 — das ist keine theoretische Gefahr).

    Kostet der Resource Governor selbst Performance?

    Der laufende Betrieb ist praktisch kostenlos — die Ressourcenzuteilung erledigt der Scheduler ohnehin, der Governor gibt ihm nur andere Regeln mit. Der einzige relevante Overhead ist die Classifier Function beim Verbindungsaufbau: Ist sie schlank gebaut, reden wir über Mikrosekunden. Ist sie es nicht, haben Sie ein selbstgemachtes Problem (siehe Warnbox in Kapitel 3).

    MAX_CPU_PERCENT oder CAP_CPU_PERCENT — was soll ich nehmen?

    Als Standardempfehlung: MAX. Es drosselt nur dann, wenn tatsächlich Konkurrenz herrscht, und lässt Ressourcen nicht ungenutzt brachliegen — der Export darf nachts Vollgas geben und ist schneller fertig. CAP ist das Werkzeug für Sonderfälle: garantiert vorhersagbares Verhalten, interne Leistungsverrechnung, oder wenn ein Prozess auch ohne Konkurrenz nachweislich Schaden anrichtet (etwa durch Storage-Sättigung, die andere Systeme auf demselben SAN trifft).

    Was gewinnt: MAX_DOP der Workload Group oder die Serverkonfiguration?

    Die Workload Group übersteuert die serverweite Einstellung für ihre Requests. Ein Query-Hint OPTION (MAXDOP n) kann innerhalb der Group wiederum abweichen — aber nur nach unten bzw. bis zum Group-Limit: Das MAX_DOP der Group wirkt als harte Obergrenze, über die auch ein Hint nicht hinauskommt. Genau dafür ist es da — es entmachtet die „ich hab mir MAXDOP 16 in die Query geschrieben"-Fraktion zuverlässig.

    Kann ich die Klassifizierung über den Anwendungsnamen steuern?

    Technisch ja, über APP_NAME() — aber mit einer wichtigen Einschränkung: Der Application Name ist ein frei setzbares Feld im Connection String. Jeder, der seinen Connection String ändern kann, kann sich damit in eine andere Group mogeln. Für Komfort-Szenarien („alles, was nach Excel aussieht, in den Reporting-Pool") ist das völlig in Ordnung; als belastbare Grenze taugt nur die Identität, also Login-Name oder AD-Gruppenmitgliedschaft per IS_MEMBER().

    Hilft der Resource Governor gegen tempdb-Probleme?

    Nur sehr indirekt. Es gibt kein tempdb-Platzkontingent pro Pool. Was Sie tun können: über REQUEST_MAX_MEMORY_GRANT_PERCENT und MAX_DOP die Abfragen zähmen, die typischerweise massive Sort-/Hash-Spills nach tempdb verursachen — das reduziert die tempdb-Last als Nebeneffekt. Für echte tempdb-Sorgen bleiben die klassischen Mittel: ausreichend Datendateien, schnelles Storage und Query-Tuning.

    Ist der Resource Governor ein Ersatz für Query-Optimierung?

    Nein — er ist die Ergänzung dafür. Der Resource Governor beantwortet die Frage „wer darf wie viel", nicht „warum braucht diese Abfrage so viel". Die nachhaltige Reihenfolge in jedem Projekt: erst messen, dann die schlimmsten Abfragen tunen, und den Resource Governor als Schutzschicht darüberlegen, damit die verbleibenden Ressourcenfresser die Kernanwendung nicht mehr treffen können. Wer nur deckelt und nie tunt, verwaltet seine Probleme, statt sie zu lösen.

     

    boddenberg.de — IT-Consulting · Software Engineering · Technologieseminare. Fragen zum Resource Governor, zu SQL-Server-Performance oder HA-Architekturen? Sprechen Sie mich an.