Planen von Batches oder Tasks in SQL Server

Jede Instanz von SQL Server ist ein getrennter Betriebssystemprozess. Jede Instanz muss potenziell Tausende von gleichzeitigen Anforderungen von Benutzern verarbeiten. Instanzen von SQL Server verwenden Microsoft Windows-Threads oder bei entsprechender Konfigurierung Fibers, um diese gleichzeitigen Tasks effizient zu verwalten. Jede Instanz von SQL Server führt immer mehrere Threads für Systemprozesse aus. Dazu gehören ein oder mehrere Threads für jede Server-Netzwerkbibliothek, ein Netzwerkthread zur Verarbeitung von Netzwerk-E/A-Vorgängen und ein Signalthread für die Kommunikation mit dem Dienstkontroll-Manager.

Grundlegendes zum Planen

Jede Instanz von SQL Server verfügt über eine interne Schicht, die eine einem Betriebssystem ähnliche Umgebung implementiert. Diese interne Schicht wird für die Planung und Synchronisierung gleichzeitiger Tasks verwendet, ohne dass dabei der Windows-Kernel aufgerufen werden muss. Diese interne Schicht kann auch Fibers oder Windows-Threads effektiv planen. Jede Instanz von SQL Server verwaltet einen Pool aus Windows-Threads oder Fibers zur Verarbeitung von Benutzerabfragen. Die maximale Größe dieses Pools wird durch die Serverkonfigurationsoption max worker threads gesteuert.

Für das Verständnis, wie eine Anforderung oder ein Task verarbeitet wird, ist es hilfreich, sich über die folgenden grundlegenden Begriffe im Klaren zu sein:

  • Verbindung
    Eine Verbindung gilt als hergestellt, wenn der Benutzer sich erfolgreich angemeldet hat. Der Benutzer kann anschließend eine oder mehrere Transact-SQL-Anweisungen zur Ausführung senden. Eine Verbindung wird geschlossen, wenn sich der Benutzer explizit abmeldet oder die Verbindung beendet wird.

  • Batch
    Ein SQL-Batch ist eine Gruppe aus einer oder mehreren Transact-SQL-Anweisungen, die von einem Client zur Ausführung an eine Instanz von SQL Server gesendet wird. Ein Batch stellt eine Arbeitseinheit dar, die von Benutzern an Database Engine (Datenbankmodul) gesendet wird.

  • Task
    Ein Task stellt eine Arbeitseinheit dar, die von SQL Server geplant ist. Ein Batch kann einem oder mehreren Tasks zugeordnet sein. Eine parallele Abfrage wird z. B. durch mehrere Tasks ausgeführt.

  • Windows-Thread
    Jeder Windows-Thread stellt einen unabhängigen Ausführungsmechanismus dar.

  • Fiber
    Eine Fiber ist ein Lightweightthread, der weniger Ressourcen beansprucht als ein Windows-Thread und im Benutzermodus den Kontext wechseln kann. Ein Windows-Thread kann mehreren Fibers zugeordnet werden.

  • Arbeitsthread
    Der Arbeitsthread stellt in SQL Server einen logischen Thread dar, der intern eins zu eins zugeordnet ist, und zwar entweder einem Windows-Thread oder – bei aktiviertem Lightweightpooling – einer Fiber. Die Zuordnung wird beibehalten, bis die Zuordnung des Arbeitsthreads aufgehoben wird, was entweder aus Mangel an Arbeitsspeicher geschieht, oder wenn sich der Arbeitsthread über lange Zeit im Leerlauf befunden hat. Die Zuordnung eines Tasks zu einem Arbeitsthread wird für die gesamte Lebensdauer des Tasks aufrechterhalten.

Verwalten von Benutzerverbindungen und Arbeitsthreadressourcen

Obwohl Threads und Fibers zwar nur in geringem Umfang Ressourcen beanspruchen, kann sich der Verbrauch von Ressourcen jedoch summieren. In Systemen mit Hunderten oder Tausenden von Benutzerverbindungen können genug Ressourcen beansprucht werden, um die Effizienz von SQL Server zu beeinträchtigen, wenn für jede Verbindung ein Thread oder eine Fiber verwendet wird. Darüber hinaus ist die Zuordnung eines dedizierten Threads für jede Benutzerverbindung nicht notwendig, da die meisten Verbindungen tatsächlich einen Großteil der Zeit damit verbringen, auf Batches zu warten, die vom Client gesendet werden. Stattdessen verwendet die Instanz von SQL Server einen Pool von Arbeitsthreads. Der Pool von Arbeitsthreads muss nur groß genug sein, damit die Anzahl der Benutzerverbindungen bedient werden kann, die in dieser Instanz gleichzeitig aktiv Batches ausführen. Wenn die max worker threads-Option auf ihrem Standardwert von 0 belassen wird, kann die Instanz von SQL Server Benutzerverbindungen effektiv mehreren verschiedenen Arbeitsthreads zuordnen. Damit wird sichergestellt, dass sie nicht zu viele Ressourcen beanspruchen.

Konfigurieren von SQL Server für Fibers

Durch die Serverkonfigurationsoption lightweight pooling wird gesteuert, ob eine Instanz von SQL Server Threads oder Fibers verwendet. Der Standardwert für diese Option ist 0. Das bedeutet, dass die Instanz von SQL Server einen Windows-Thread pro Arbeitsthread plant, und zwar maximal so viele, wie durch den Wert der Option max worker threads festgelegt ist. Wenn lightweight pooling auf 1 festgelegt ist, verwendet SQL Server Fibers anstelle von Windows-Threads. Dies wird als Ausführung im Fibermodus bezeichnet. Im Fibermodus ordnet eine Instanz von SQL Server einen Windows-Thread pro SQL-Zeitplanungsmodul zu und ordnet dann eine Fiber pro Arbeitsthread zu, und zwar maximal so viele, wie durch den Wert der Option max worker threads festgelegt ist. Unabhängig davon, ob Windows-Threads oder Fibers verwendet werden, setzt eine Instanz von SQL Server dieselben Algorithmen für die Planung und Synchronisierung von Tasks ein. SQL Server Express unterstützt keine Fibers. Weitere Informationen finden Sie unter Verwenden der Option lightweight pooling. Es wird empfohlen, die Fibermodusplanung nicht für Routinevorgänge zu verwenden. Der Grund hierfür liegt darin, dass es zu Leistungseinbußen führen kann, wenn die gängigen Vorteile des Kontextwechsels nicht genutzt werden können, und dass einige Komponenten von SQL Server im Fibermodus nicht ordnungsgemäß arbeiten können. Weitere Information finden Sie unter Lightweightpooling.

Funktionsweise der Batch- oder Taskplanung

Wenn eine Anwendung eine Verbindung mit Database Engine (Datenbankmodul) herstellt, wird ihr eine Sitzungs-ID (SPID) zugewiesen. Alle Informationen, die für die Lebensdauer der Verbindung verwaltet werden müssen, werden in internen Datenstrukturen verwaltet, die der SPID zugeordnet sind. Wenn eine Instanz von SQL Server Batches von den Clients empfängt, gliedert sie den Batch in einen oder mehrere Tasks auf und ordnet dann jeden Task einem verfügbaren Arbeitsthread aus einem Pool von Arbeitsthreads zu. Für die gesamte Lebensdauer eines Tasks wird ein Arbeitsthread an den Task gebunden. Ein Arbeitsthread führt die Abfrage auf dem zugewiesenen SQL-Zeitplanungsmodul aus. Wenn es keine freien Arbeitsthreads gibt und der Wert der max worker threads-Option noch nicht erreicht ist, ordnet die Instanz von SQL Server dem neuen Batch einen neuen Arbeitsthread zu. Wenn keine freien Threads oder Fibers verfügbar sind und der Wert für max worker threads bereits erreicht ist, blockiert die Instanz von SQL Server den neuen Task, bis ein Arbeitsthread wieder freigegeben wird.

Nachdem einem Task ein Arbeitsthread zugeordnet wurde, bleibt diese Zuordnung zum Task bestehen, bis der Task abgeschlossen ist, z. B. bis das letzte der vom Batch generierten Resultsets zum Client zurückgegeben wurde. Zu diesem Zeitpunkt wird der Thread freigegeben und kann den Tasks zugewiesen werden, die zum nächsten Batch gehören.

Die aktive Ausführung von Operationen für eine Verbindung durch Database Engine (Datenbankmodul) ist lediglich vom Zeitpunkt des Empfangs eines Batches bis zur Rückgabe der Ergebnisse an den Client erforderlich. Während dieser Periode kann es Zeiten geben, in denen der Batch keine aktive Verarbeitung erfordert. So kann es z. B. Zeiten geben, in denen Database Engine (Datenbankmodul) darauf warten muss, dass ein Lesevorgang die Daten abruft, die für die aktuelle Abfrage benötigt werden, oder darauf warten muss, dass ein anderer Batch eine Sperre aufhebt. Die Zuordnung zwischen Task und Arbeitsthread wird selbst dann beibehalten, wenn der Task auf einer Ressource blockiert ist.

Immer wenn Database Engine (Datenbankmodul) die Verarbeitung eines Tasks startet, der einem Batch zugeordnet ist, erfolgt die Zeitplanung des dem Task zugeordneten Arbeitsthreads, um die erforderlichen Operationen auszuführen. Nachdem der Arbeitsthread die Operationen für den Task abgeschlossen hat, teilt die Instanz von SQL Server den Arbeitsthread dem nächsten Task zu, der zur Ausführung bereitsteht. Eine SPID für eine Verbindung bleibt für die gesamte Lebensdauer der Verbindung konstant. Bei lang andauernden Verbindungen können die einzelnen Batchtasks durch viele verschiedene Arbeitsthreads ausgeführt werden. So können z. B. die Tasks aus dem ersten Batch durch worker1 ausgeführt werden, während die Tasks aus dem zweiten Batch durch worker2 ausgeführt werden könnten. Einige Anweisungen können auch parallel ausgeführt werden. In diesem Fall kann ein Batch mehrere Tasks enthalten, die durch mehrere Arbeitsthreads gleichzeitig ausgeführt werden.