Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Gilt für:SQL Server
Azure SQL-Datenbank
Azure SQL Managed Instance
Azure Synapse Analytics
SQL-Datenbank in Microsoft Fabric
Der Abfrageoptimierer verwendet Statistiken zum Erstellen von Abfrageplänen, die die Abfrageleistung verbessern. Für die meisten Abfragen generiert der Abfrageoptimierer bereits die erforderlichen Statistiken für einen qualitativ hochwertigen Abfrageplan. In einigen Fällen müssen Sie zusätzliche Statistiken erstellen oder den Abfrageentwurf ändern, um optimale Ergebnisse zu erzielen. Dieser Artikel bietet eine Erläuterung von Statistikkonzepten sowie Leitlinien zur effektiven Verwendung von Abfrageoptimierungsstatistiken.
Komponenten und Konzepte
Statistics
Statistiken zur Abfrageoptimierung sind binäre große Objekte (BLOBs), die statistische Informationen über die Verteilung von Werten in einer oder mehreren Spalten einer Tabelle oder indizierten Ansicht enthalten. Der Abfrageoptimierer verwendet diese Statistiken, um die Kardinalität oder Anzahl von Zeilen im Abfrageergebnis zu schätzen. Diese Kardinalitätsschätzungen ermöglichen es dem Abfrageoptimierer, einen hochwertigen Abfrageplan zu erstellen. Beispielsweise kann der Abfrageoptimierer, abhängig von Ihren Prädikaten, Kardinalitätsschätzungen verwenden, um statt des ressourcenintensiveren Operators „Index Scan“ den Operator „Index Seek“ auszuwählen, wenn auf diese Weise die Abfrageleistung verbessert werden kann.
Jedes Statistikobjekt wird für eine Liste mit mindestens einer Tabellenspalte erstellt und enthält ein Histogramm, das die Verteilung von Werten in der ersten Spalte anzeigt. Statistikobjekte, die sich auf mehrere Spalten beziehen, enthalten außerdem statistische Informationen über die spaltenübergreifende Korrelation von Werten. Diese Korrelationsstatistiken oder Dichtenwerden von der Anzahl unterschiedlicher Zeilen mit Spaltenwerten abgeleitet.
Histogram
Ein Histogramm misst die Häufigkeit des Vorkommens für jeden unterschiedlichen Wert in einem Dataset. Der Abfrageoptimierer berechnet ein Histogramm für die Spaltenwerte in der ersten Schlüsselspalte des Statistikobjekts und wählt die Spaltenwerte aus, indem statistische Zeilenstichproben entnommen werden oder indem ein vollständiger Scan aller Zeilen in der Tabelle oder Sicht ausgeführt wird. Wenn das Histogramm aus einer stichprobenierten Reihe von Zeilen erstellt wird, sind die gespeicherten Summen für die Anzahl der Zeilen und die Anzahl unterschiedlicher Werte Schätzungen und müssen nicht ganze Ganze Zahlen sein.
Note
SQL Server erstellt Histogramme nur für eine einzelne Spalte – die erste Spalte in der Gruppe der Schlüsselspalten des Statistikobjekts.
Zum Erstellen des Histogramms sortiert der Abfrageoptimierer die Spaltenwerte, berechnet die Anzahl der Werte, die den einzelnen unterschiedlichen Spaltenwerten entsprechen, und aggregiert die Spaltenwerte dann in maximal 200 zusammenhängenden Histogrammschritten. Jeder Histogrammschritt umfasst einen Bereich von Spaltenwerten gefolgt von einem oberen Spaltengrenzwert. Der Bereich enthält alle möglichen Spaltenwerte zwischen den Begrenzungswerten, ohne die Begrenzungswerte selbst. Der niedrigste der sortierten Spaltenwerte ist der obere Grenzwert für den ersten Histogrammschritt.
SQL Server erstellt das Histogramm aus den sortierten Spaltenwerten in drei Schritten:
- Initialisierung des Histogramms: Im ersten Schritt wird eine Wertesequenz verarbeitet, die am Anfang der sortierten Menge beginnt, und bis zu 200 Werte von range_high_key, equal_rows, range_rows, und distinct_range_rows werden erfasst (range_rows und distinct_range_rows sind während dieses Schritts immer 0). Der erste Schritt endet entweder, wenn alle Eingaben erschöpft sind oder wenn 200 Werte gefunden werden.
- Scannen mit Bucketzusammenführung: Jeder zusätzliche Wert aus der führenden Spalte des Statistikschlüssels wird im zweiten Schritt in sortierter Reihenfolge verarbeitet. Jeder nachfolgende Wert wird entweder zum letzten Bereich hinzugefügt, oder am Ende wird ein neuer Bereich erstellt (diese Sortierung ist möglich, da die Eingabewerte sortiert sind). Wenn ein neuer Bereich erstellt wird, reduziert der Prozess ein Paar vorhandener benachbarter Bereiche in einen einzelnen Bereich. Dieses Bereichspaar wird ausgewählt, um den Verlust von Informationen zu minimieren. Diese Methode verwendet einen Algorithmus für die maximale Differenz, um die Anzahl von Schritten im Histogramm zu minimieren und gleichzeitig die Differenz zwischen den Begrenzungswerten zu maximieren. Die Anzahl von Schritten nach dem Reduzieren von Bereichen bleibt in diesem Schritt bei 200.
- Konsolidierung des Histogramms: Im dritten Schritt können weitere Bereiche reduziert werden, wenn dabei keine erhebliche Menge an Informationen verloren geht. Die Anzahl von Histogrammschritten kann geringer sein als die Anzahl unterschiedlicher Werte, auch bei Spalten mit weniger als 200 Grenzpunkten. Wenn jede Spalte mehr als 200 eindeutige Werte enthält, kann das Histogramm daher weniger als 200 Schritte enthalten. Für eine Spalte, die nur aus eindeutigen Werten besteht, weist das konsolidierte Histogramm mindestens drei Schritte auf.
Note
Wenn das Histogramm mit einer Stichprobe und nicht mit Vollscan erstellt wird, sind die Werte von equal_rows, range_rows, distinct_range_rows und average_range_rows Schätzungen und müssen daher keine ganzen Zahlen sein.
Das folgende Diagramm zeigt ein Histogramm mit sechs Schritten. Der Bereich links vom ersten oberen Grenzwert ist der erste Schritt.
Folgendes gilt für jeden Histogrammschritt im vorherigen Beispiel:
Die fett formatierte Linie stellt den oberen Grenzwert (range_high_key) und die Häufigkeit dar, mit der sie auftritt (equal_rows).
Der einfarbige Bereich links von range_high_key stellt den Bereich der Spaltenwerte dar und die durchschnittliche Anzahl der Vorkommen jedes Spaltenwerts (average_range_rows). average_range_rows ist für den ersten Histogrammschritt immer 0.
Die gepunkteten Linien stellen die stichprobenierten Werte dar, die verwendet werden, um die Gesamtanzahl unterschiedlicher Werte im Bereich (distinct_range_rows) und die Gesamtanzahl der Werte im Bereich (range_rows) zu schätzen. Der Abfrageoptimierer verwendet range_rows und distinct_range_rows, um average_range_rows zu berechnen. Die als Stichprobe entnommenen Werte werden nicht gespeichert.
Dichtevektor
Die Dichte enthält Informationen zur Anzahl von Duplikaten in einer bestimmten Spalte oder Spaltenkombination und wird als 1/(Anzahl der unterschiedlichen Werte) berechnet. Der Abfrageoptimierer verwendet Dichten, um Kardinalitätsschätzungen für Abfragen zu erweitern, die mehrere Spalten aus derselben Tabelle oder indizierten Sicht zurückgeben. Bei einer Verringerung der Dichte erhöht sich die Selektivität eines Werts. In einer Tabelle für Autos stammen z. B. viele Autos von demselben Hersteller, jedes Auto verfügt jedoch über eine eindeutige Fahrzeugnummer. Ein Index für das VIN-Objekt weist eine höhere Selektivität auf als ein Index für den Hersteller, da „VIN“ eine niedrigere Dichte als „Hersteller“ aufweist.
Note
Die Häufigkeit enthält Informationen über das Auftreten der einzelnen unterschiedlichen Werte in der ersten Schlüsselspalte des Statistikobjekts und wird als row count * density berechnet. In Spalten mit eindeutigen Werten kann eine maximale Häufigkeit von 1 gefunden werden.
Der Dichtevektor enthält eine Dichte für jedes Präfix von Spalten im Statistikobjekt. Wenn beispielsweise ein Statistikobjekt die Schlüsselspalten CustomerId, ItemId und Price aufweist, wird die Dichte für jedes der folgenden Spaltenpräfixe berechnet.
| Spaltenpräfix | Dichte berechnet für |
|---|---|
(CustomerId) |
Zeilen mit übereinstimmenden Werten für CustomerId |
(CustomerId, ItemId) |
Zeilen mit übereinstimmenden Werten für CustomerId und ItemId |
(CustomerId, ItemId, Price) |
Zeilen mit übereinstimmenden Werten für CustomerId, ItemId und Price |
Gefilterte Statistiken
Gefilterte Statistiken können die Abfrageleistung für Abfragen verbessern, bei denen aus klar definierten Teilmengen von Daten ausgewählt wird. Gefilterte Statistiken verwenden ein Filterprädikat, um die Teilmenge von Daten auszuwählen, die in der Statistik enthalten ist. Sorgfältig entworfene gefilterte Statistiken können den Abfrageausführungsplan im Vergleich zu Tabellenstatistiken verbessern. Weitere Informationen zum Filter-Prädikat finden Sie unter CREATE STATISTICS. Weitere Informationen zum Zeitpunkt der Erstellung von gefilterten Statistiken finden Sie im Abschnitt Zeitpunkt der Erstellung von Statistiken in diesem Artikel.
Statistikoptionen
Sie können Optionen konfigurieren, die sich darauf auswirken, wann und wie das System Statistiken erstellt und aktualisiert. Sie können diese Optionen nur auf Datenbankebene festlegen.
AUTO_CREATE_STATISTICS-Option
Wenn Sie die Option AUTO_CREATE_STATISTICS zum automatischen Erstellen von Statistiken aktivieren, erstellt der Abfrageoptimierer bei Bedarf Statistiken für einzelne Spalten im Abfrageprädikat, um die Kardinalitätsschätzungen für den Abfrageplan zu verbessern. Diese Statistiken für einzelne Spalten werden für Spalten erstellt, die noch nicht über ein Histogramm in einem vorhandenen Statistikobjekt verfügen. Die AUTO_CREATE_STATISTICS Option bestimmt nicht, ob die Datenbank Statistiken für Indizes erstellt. Diese Option generiert auch keine gefilterten Statistiken. Sie gilt ausschließlich für Statistiken für einzelne Spalten der gesamten Tabelle.
Erstellt der Abfrageoptimierer Statistiken als Ergebnis der Verwendung der AUTO_CREATE_STATISTICS-Option, beginnt der Statistikname mit _WA. Mit der folgenden Abfrage können Sie ermitteln, ob der Abfrageoptimierer Statistiken für eine Abfrage-Prädikatspalte erstellt hat.
SELECT OBJECT_NAME(s.object_id) AS object_name,
COL_NAME(sc.object_id, sc.column_id) AS column_name,
s.name AS statistics_name
FROM sys.stats AS s
INNER JOIN sys.stats_columns AS sc
ON s.stats_id = sc.stats_id
AND s.object_id = sc.object_id
WHERE s.name LIKE '_WA%'
ORDER BY s.name;
Option „AUTO_UPDATE_STATISTICS“
Wenn Sie die Option "Statistiken zur automatischen Aktualisierung" aktivieren, AUTO_UPDATE_STATISTICS, bestimmt der Abfrageoptimierer, wann Statistiken möglicherweise veraltet sind, und aktualisiert diese, wenn eine Abfrage sie verwendet. Diese Aktion wird auch als Neukompilierung von Statistiken bezeichnet. Statistiken sind veraltet, wenn die Datenverteilung in der Tabelle oder indizierten Sicht durch die Vorgänge INSERT, UPDATE, DELETE oder MERGE geändert wurde. Der Abfrageoptimierer zählt die Anzahl der Zeilenänderungen seit der letzten Aktualisierung der Statistik und vergleicht diese Zahl mit einem Schwellenwert, um festzustellen, ob Statistiken veraltet sein könnten. Der Schwellenwert basiert auf der Tabellenkardinalität, bei der es sich um die Anzahl der Zeilen in der Tabellen- oder indizierten Ansicht handelt.
Das Markieren von Statistiken als veraltet basierend auf Zeilenänderungen erfolgt auch dann, wenn die AUTO_UPDATE_STATISTICS Option ist OFF. Wenn die AUTO_UPDATE_STATISTICS Option lautet OFF, aktualisiert das System keine Statistiken, auch wenn es sie als veraltet markiert. Pläne verwenden weiterhin veraltete Statistikobjekte. Das Festlegen von AUTO_UPDATE_STATISTICS auf OFF kann zu suboptimalen Abfrageplänen und einer beeinträchtigten Abfrageleistung führen. Legen Sie die AUTO_UPDATE STATISTICS Option auf ON.
Bis zu SQL Server 2014 (12.x) verwendet die Datenbank-Engine einen Schwellenwert für die Neukompilierung, der auf der Anzahl der Zeilen in der Tabelle oder indizierten Sicht zum Zeitpunkt der Auswertung der Statistik basiert. Der Schwellenwert unterscheidet sich je nachdem, ob eine Tabelle temporär oder dauerhaft ist.
Tabellentyp Tabellenkardinalität (n) Schwellenwert für Neukompilierung (Anzahl von Änderungen) Temporary n< 6 6 Temporary 6 <= n<= 500 500 Permanent N<= 500 500 Temporär oder permanent n> 500 500 + (0,20 * n) Wenn Ihre Tabelle zum Beispiel 20.000 Zeilen enthält, ist die Berechnung
500 + (0.2 * 20,000) = 4,500, und die Statistiken werden alle 4.500 Änderungen aktualisiert.Ab SQL Server 2016 (13.x) und mit dem Datenbank-Kompatibilitätsgrad 130 verwendet das Datenbankmodul einen abnehmenden, dynamischen Schwellenwert für die Neukompilierung von Statistiken, der entsprechend der Tabellenkardinalität zum Zeitpunkt der Auswertung der Statistiken angepasst wird. Mit dieser Änderung werden Statistiken zu großen Tabellen häufiger aktualisiert. Wenn eine Datenbank jedoch eine Kompatibilitätsstufe unter 130 aufweist, gelten die Schwellenwerte für die SQL Server 2014 (12,x).
Tabellentyp Tabellenkardinalität (n) Schwellenwert für Neukompilierung (Anzahl von Änderungen) Temporary n < 66 Temporary 6 <= n <= 500500 Permanent n <= 500500 Temporär oder permanent n > 500MIN ( 500 + (0.20 * n), SQRT(1,000 * n) )Wenn Ihre Tabelle beispielsweise 2 Millionen Zeilen enthält, ist die Berechnung das Minimum von
500 + (0.20 * 2,000,000) = 400,500undSQRT(1,000 * 2,000,000) = 44,721. Dies bedeutet, dass die Statistiken alle 44.721 Änderungen aktualisiert werden.
Important
Aktivieren Sie in SQL Server 2008 R2 (10.50.x) bis SQL Server 2014 (12.x) oder in SQL Server 2016 (13.x) und höher bei einem Kompatibilitätsgrad der Datenbank von 120 und älteren Versionen das Ablaufverfolgungsflag 2371, sodass SQL Server einen abnehmenden Schwellenwert für dynamische Statistikaktualisierungen verwendet.
Obwohl für alle Szenarien empfohlen, ist das Aktivieren des Ablaufverfolgungsflags 2371 optional. Gehen Sie jedoch folgendermaßen vor, um das Ablaufverfolgungsflag 2371 in Ihrer Umgebung vor SQL Server 2016 (13.x) zu aktivieren:
- Auf einem SAP-System sollten Sie diese Ablaufverfolgung aktivieren. Weitere Informationen finden Sie in diesem Blog zum Ablaufverfolgungsflag 2371.
- Wenn Sie sich auf einen nächtlichen Auftrag verlassen müssen, um Statistiken zu aktualisieren, weil die aktuelle automatische Aktualisierung nicht häufig genug ausgelöst wird, sollten Sie in Betracht ziehen, Traceflag 2371 zu aktivieren, um den Schwellenwert an die Kardinalität der Tabelle anzupassen.
Bevor der Abfrageoptimierer eine Abfrage kompiliert und einen zwischengespeicherten Abfrageplan ausführt, sucht er nach veralteten Statistiken. Bevor eine Abfrage kompiliert wird, verwendet der Abfrageoptimierer die Spalten, Tabellen und indizierten Ansichten im Abfrage-Prädikat, um zu bestimmen, welche Statistiken veraltet sein könnten. Vor dem Ausführen eines zwischengespeicherten Abfrageplans stellt die Datenbank-Engine sicher, dass der Abfrageplan auf aktuelle Statistiken verweist.
Die AUTO_UPDATE_STATISTICS Option gilt für Statistikobjekte, die für Indizes, einzelspaltige Abfrage-Prädikate und mit der CREATE STATISTICS Anweisung erstellte Statistiken erstellt wurden. Diese Option gilt auch für gefilterte Statistiken.
Sie können die sys.dm_db_stats_properties verwenden, um die Anzahl der Zeilen, die in einer Tabelle geändert wurden, genau nachzuverfolgen und zu entscheiden, ob Sie Statistiken manuell aktualisieren möchten.
AUTO_UPDATE_STATISTICS ist für speicheroptimierte Tabellen immer OFF.
AUTO_UPDATE_STATISTICS_ASYNC
Mit der AUTO_UPDATE_STATISTICS_ASYNC-Option für das asynchrone Statistikupdate wird festgelegt, ob der Abfrageoptimierer das synchrone oder asynchrone Statistikupdate verwendet. Standardmäßig ist OFFdie Option für asynchrone Statistikaktualisierungen festgelegt, und die Abfrageoptimierer aktualisiert Statistiken synchron. Die AUTO_UPDATE_STATISTICS_ASYNC Option gilt für Statistikobjekte, die für Indizes, einzelne Spalten in Abfrage-Prädikaten und mit der CREATE STATISTICS Anweisung erstellte Statistiken erstellt wurden.
Note
Um die Option für die asynchrone Statistikaktualisierung in SQL Server Management Studio festzulegen, legen Sie auf der Seite "Optionen" des Fensters "Datenbankeigenschaften" sowohl "Auto Update Statistics" als auch "Auto Update Statistics" asynchron auf "True" fest.
Statistikaktualisierungen können entweder synchron (Standard) oder asynchron sein.
Mit synchronen Statistikaktualisierungen werden Abfragen immer mit aktuellen Statistiken kompiliert und ausgeführt. Wenn Statistiken veraltet sind, wartet der Abfrageoptimierer auf aktualisierte Statistiken, bevor er die Abfrage kompiliert und ausführt.
Mit asynchronen Statistikaktualisierungen werden Abfragen mit vorhandenen Statistiken kompiliert, selbst wenn diese veraltet sind. Der Abfrageoptimierer könnte einen suboptimalen Abfrageplan auswählen, wenn Statistiken beim Kompilieren der Abfrage veraltet sind. Statistiken werden in der Regel kurz darauf aktualisiert. Abfragen, die nach dem Abschluss der Statistikaktualisierungen kompiliert werden, profitieren von der Verwendung der aktualisierten Statistiken.
Verwenden Sie ggf. synchrone Statistiken, wenn Sie Vorgänge ausführen, die die Verteilung der Daten ändern, beispielsweise das Kürzen einer Tabelle oder das Ausführen eines Massenupdates für einen großen Zeilenprozentsatz. Wenn Sie die Statistiken nach Abschluss des Vorgangs nicht manuell aktualisieren, stellt die Verwendung der synchronen Statistikaktualisierung sicher, dass die Statistiken aktuell sind, bevor Abfragen sie benötigen.
In den folgenden Szenarien empfiehlt sich die Verwendung asynchroner Statistiken, um besser vorhersagbare Antwortzeiten für Abfragen zu erzielen:
Häufig werden von der Anwendung die gleichen Abfragen, ähnliche Abfragen bzw. ähnliche zwischengespeicherte Abfragepläne ausgeführt. Bei Verwendung asynchroner Statistikaktualisierungen können die Antwortzeiten für Abfragen vorhersagbarer sein als bei synchronen Statistikaktualisierungen, weil der Abfrageoptimierer eingehende Abfragen direkt ausführen kann, ohne auf aktuelle Statistiken zu warten. Dadurch wird verhindert, dass sich einige Abfragen verzögern und andere nicht.
Bei Ihrer Anwendung sind Zeitüberschreitungen bei Clientanforderungen aufgetreten, die dadurch verursacht wurden, dass eine oder mehrere Abfragen auf aktualisierte Statistiken warten. In einigen Fällen kann das Warten auf synchrone Statistiken dazu führen, dass Anwendungen mit aggressiven Timeouts fehlschlagen.
Note
Statistiken zu lokalen temporären Tabellen werden unabhängig von der AUTO_UPDATE_STATISTICS_ASYNC Option immer synchron aktualisiert. Statistiken zu globalen temporären Tabellen werden synchron oder asynchron entsprechend der AUTO_UPDATE_STATISTICS_ASYNC für die Benutzerdatenbank festgelegten Option aktualisiert.
Asynchrone Statistikupdates werden von einer Hintergrundanforderung ausgeführt. Wenn die Anforderung bereit ist, aktualisierte Statistiken in die Datenbank zu schreiben, versucht sie, eine Schemaänderungssperre für das Statistikmetadatenobjekt zu erhalten. Wenn eine andere Sitzung bereits eine Sperre für dasselbe Objekt verwendet, wird das asynchrone Statistikupdate blockiert, bis die Schemaänderungssperre abgerufen werden kann. Ebenso werden Sitzungen, die zum Kompilieren einer Abfrage eine Schemastabilitätssperre (Sch-S) für das Statistikmetadatenobjekt abrufen müssen, möglicherweise durch die Hintergrundsitzung für die asynchrone Statistikaktualisierung blockiert, die bereits die Schemaänderungssperre verwendet oder darauf wartet, diese abzurufen. Daher erhöht sich durch die Verwendung von asynchronen Statistiken für Arbeitsauslastungen mit sehr häufigen Abfragekompilierungen und häufigen Statistikaktualisierungen möglicherweise die Wahrscheinlichkeit, dass aufgrund einer Blockierung durch Sperren Parallelitätsprobleme auftreten.
In Azure SQL-Datenbank, Azure SQL Managed Instance und ab SQL Server 2022 (16.x) können Sie potenzielle Parallelitätsprobleme mithilfe einer asynchronen Statistikaktualisierung vermeiden, wenn Sie die ASYNC_STATS_UPDATE_WAIT_AT_LOW_PRIORITYKonfiguration mit Datenbankbereich aktivieren. Wenn diese Konfiguration aktiviert ist, wartet die Hintergrundanforderung auf das Abrufen der Schemaänderungssperre (Sch-M) und behält die aktualisierte Statistik in einer separaten Warteschlange mit niedriger Priorität, sodass andere Anforderungen mit der Kompilierung von Abfragen mit vorhandenen Statistiken fortfahren können. Sobald keine andere Sitzung mehr eine Sperre für das Statistikmetadatenobjekt verwendet, ruft die Hintergrundanforderung die Schemaänderungssperre ab und aktualisiert die Statistiken. Im unwahrscheinlichen Fall, dass die Hintergrundanforderung die Sperre innerhalb eines Timeoutzeitraums von mehreren Minuten nicht abrufen kann, wird die asynchrone Statistikaktualisierung abgebrochen, und die Statistiken werden erst aktualisiert, wenn eine andere automatische Statistikaktualisierung ausgelöst wird, oder bis Statistiken manuell aktualisiert werden.
Note
Die ASYNC_STATS_UPDATE_WAIT_AT_LOW_PRIORITY Konfigurationsoption mit Datenbankbereich ist in Azure SQL-Datenbank, Azure SQL Managed Instance und in SQL Server ab SQL Server 2022 (16.x) verfügbar.
Option AUTO_DROP
Gilt für: Azure SQL-Datenbank, Azure SQL Managed Instance und SQL Server 2022 (16.x) und höher
Wenn Sie in SQL Server vor SQL Server 2022 (16.x) manuell Statistiken erstellen oder ein Drittanbietertool für eine Benutzerdatenbank verwenden, können diese Statistikobjekte Schemaänderungen blockieren oder beeinträchtigen.
Ab SQL Server 2022 (16.x) ist die Option AUTO_DROP standardmäßig für alle neuen und migrierten Datenbanken aktiviert. Wenn Sie die AUTO_DROP Eigenschaft aktivieren, erstellt die Datenbank Statistikobjekte in einem Modus, sodass eine nachfolgende Schemaänderung nicht vom Statistikobjekt blockiert wird, sondern die Statistiken bei Bedarf gelöscht werden. Auf diese Weise verhalten sich manuell erstellte Statistiken mit aktivierter Option AUTO_DROP wie automatisch erstellte Statistiken.
In Azure SQL-Datenbank, Azure SQL Managed Instance und SQL Server 2022 (16.x) und höheren Versionen verhalten sich automatisch erstellte Statistiken immer so, als ob die AUTO_DROP aktiviert ist.
Note
Wenn Sie versuchen, die Eigenschaft AUTO_DROP für automatisch erstellte Statistiken festzulegen oder zu deaktivieren, können Fehler auftreten. Automatisch erstellte Statistiken verwenden immer die Option Auto_Drop. Bei einigen Sicherungen kann diese Eigenschaft nach der Wiederherstellung falsch eingestellt sein, bis das Statistikobjekt das nächste Mal (manuell oder automatisch) aktualisiert wird. Automatisch erstellte Statistiken verhalten sich jedoch immer wie automatisch gelöschte Statistiken. Beim Wiederherstellen einer Datenbank auf SQL Server 2022 (16.x) aus einer früheren Version wird empfohlen, sp_updatestats auf der Datenbank auszuführen, wobei die richtigen Metadaten für die Funktion des automatischen Löschens von Statistiken festgelegt werden.
Hiermit können Sie beispielsweise ein Statistikobjekt manuell in der Tabelle dbo.DatabaseLog erstellen:
CREATE STATISTICS [mystats]
ON [dbo].[DatabaseLog]([DatabaseLogID], [PostTime], [DatabaseUser])
WITH AUTO_DROP = ON;
Hiermit können Sie beispielsweise die Auto-Drop-Einstellung eines Statistikobjekts in der dbo.DatabaseLog-Tabelle aktualisieren:
UPDATE STATISTICS [dbo].[DatabaseLog] ([mystats])
WITH AUTO_DROP = ON;
Verwenden Sie die Spalte auto_drop in sys.stats, um die Auto-Drop-Einstellung in vorhandenen Statistiken auszuwerten:
SELECT object_id,
[name],
auto_drop
FROM sys.stats;
Weitere Informationen finden Sie unter AUTO_DROP.
INCREMENTAL
Gilt für: SQL Server 2014 (12.x) und spätere Versionen.
Wenn Sie die Option INCREMENTAL von CREATE STATISTICS auf ON festlegen, erstellen Sie Statistiken pro Partition. Wenn Sie sie auf OFF festlegen, löscht die Datenbank den Statistikbaum und berechnet die Statistiken neu. Der Standardwert lautet OFF. Diese Einstellung setzt die Eigenschaft auf Datenbankebene INCREMENTAL außer Kraft.
- Weitere Informationen zum Erstellen inkrementeller Statistiken finden Sie unter CREATE STATISTICS.
- Weitere Informationen zum automatischen Erstellen von partitionsbezogenen Statistiken finden Sie unter Datenbankeigenschaften (Optionenseite) und ALTER DATABASE SET Optionen.
Wenn Sie einer großen Tabelle neue Partitionen hinzufügen, sollten Sie Statistiken aktualisieren, um die neuen Partitionen einzuschließen. Die zum Scannen der gesamten Tabelle (FULLSCAN oder SAMPLE Optionen) erforderliche Zeit kann jedoch lang sein. Außerdem ist das Scannen der gesamten Tabelle nicht erforderlich, da ggf. nur die Statistik der neuen Partitionen benötigt wird. Die inkrementelle Option erstellt und speichert Statistiken pro Partitionsbasis und aktualisiert nur Statistiken zu diesen Partitionen, die neue Statistiken benötigen.
Wenn Statistiken pro Partition nicht unterstützt werden, ignoriert die Datenbank die Option und gibt eine Warnung aus. Inkrementelle Statistiken werden für die folgenden Statistiktypen nicht unterstützt:
- Statistiken, die mit Indizes erstellt wurden, die über keine Partitionsausrichtung mit der Basistabelle verfügen.
- Statistiken, die für lesbare sekundäre Always On-Datenbanken erstellt wurden.
- Statistiken, die für schreibgeschützte Datenbanken erstellt wurden.
- Statistiken, die für gefilterte Indizes erstellt wurden.
- Statistiken, die für Sichten erstellt wurden.
- Statistiken, die für interne Tabellen erstellt wurden.
- Statistiken, die mit räumlichen Indizes oder XML-Indizes erstellt wurden.
Gründe für das Erstellen von Statistiken
Der Abfrageoptimierer erstellt bereits Statistiken in der folgenden Weise:
Wenn Sie einen Index für Tabellen oder Ansichten erstellen, erstellt der Abfrageoptimierer Statistiken für Indizes. Diese Statistiken werden für die Schlüsselspalten des Indexes erstellt. Wenn es sich um einen gefilterten Index handelt, erstellt der Abfrageoptimierer gefilterte Statistiken für die gleiche Teilmenge von Zeilen, die für den gefilterten Index angegeben wurden. Weitere Informationen zu gefilterten Indizes finden Sie unter Erstellen gefilterter Indizes und CREATE INDEX.
Note
In SQL Server 2014 (12.x) und höheren Versionen erstellt die Datenbank keine Statistiken, indem alle Zeilen in der Tabelle durchsucht werden, wenn Sie einen partitionierten Index erstellen oder neu erstellen. Der Abfrageoptimierer generiert stattdessen Statistiken mithilfe des Standardalgorithmus zur Stichprobenentnahme. Nachdem eine Datenbank mit partitionierten Indizes aktualisiert wurde, bemerken Sie möglicherweise einen Unterschied in den Histogrammdaten für diese Indizes. Diese Änderung des Verhaltens beeinträchtigt die Abfrageleistung möglicherweise nicht. Um Statistiken zu partitionierten Indizes abzurufen, indem Sie alle Zeilen in der Tabelle überprüfen, verwenden
CREATE STATISTICSOderUPDATE STATISTICSmit derFULLSCANKlausel.Der Abfrageoptimierer erstellt Statistiken für einzelne Spalten in Abfrageprädikaten, wenn AUTO_CREATE_STATISTICS aktiviert ist.
Bei den meisten Abfragen stellen diese beiden Methoden zum Erstellen von Statistiken einen qualitativ hochwertigen Abfrageplan sicher. In einigen Fällen können Sie Abfragepläne verbessern, indem Sie zusätzliche Statistiken mithilfe der CREATE STATISTICS Anweisung erstellen. Diese zusätzlichen Statistiken können statistische Korrelationen erfassen, die der Abfrageoptimierer beim Erstellen von Statistiken für Indizes oder einzelne Spalten nicht berücksichtigt. Ihre Anwendung kann über zusätzliche statistische Korrelationen in den Tabellendaten verfügen, durch die der Abfrageoptimierer Abfragepläne verbessern kann, wenn sie für die Berechnung von Statistikobjekten zugrunde gelegt werden. Der Abfrageplan kann beispielsweise optimiert werden, indem gefilterte Statistiken für eine Teilmenge von Datenzeilen oder Statistiken für mehrere Spalten für Abfrageprädikatsspalten ausgeführt werden.
Wenn Sie Statistiken mithilfe der CREATE STATISTICS Anweisung erstellen, behalten Sie die AUTO_CREATE_STATISTICS Option ON bei, sodass der Abfrageoptimierer weiterhin routinemäßig Statistiken mit einer Spalte für Abfrage-Prädikatspalten erstellt. Weitere Informationen zu Abfrageprädikaten finden Sie unter Suchbedingung.
Erwägen Sie das Erstellen von Statistiken mithilfe der CREATE STATISTICS Anweisung, wenn eine der folgenden Bedingungen zutrifft:
- Der Datenbankoptimierungsratgeber schlägt vor, Statistiken zu erstellen.
- Das Abfrage-Prädikat enthält mehrere korrelierte Spalten, die noch keine Schlüssel im selben Index sind.
- Bei der Abfrageausführung wird aus einer Teilmenge von Daten ausgewählt.
- Statistiken für eine Abfrage fehlen.
Note
Spezifische Informationen zu Tabellen und Statistiken, die sich auf In-Memory OLTP beziehen, finden Sie unter Statistiken für speicheroptimierte Tabellen.
Abfrage-Prädikat enthält mehrere korrelierte Spalten
Wenn ein Abfrageprädikat mehrere Spalten mit spaltenübergreifenden Beziehungen und Abhängigkeiten enthält, könnte der Abfrageplan durch Statistiken für mehrere Spalten optimiert werden. Statistiken für mehrere Spalten enthalten spaltenübergreifende Korrelationsstatistiken, so genannte Dichten, die in Statistiken für einzelne Spalten nicht verfügbar sind. Durch Dichten können Kardinalitätsschätzungen verbessert werden, wenn Abfrageergebnisse von Datenbeziehungen zwischen mehreren Spalten abhängig sind.
Wenn sich die Spalten bereits im selben Index befinden, ist das mehrspaltige Statistikobjekt bereits vorhanden, und Sie müssen sie nicht manuell erstellen. Wenn sich die Spalten noch nicht im selben Index befinden, können Sie mehrspaltige Statistiken erstellen, indem Sie einen Index für die Spalten oder mithilfe der CREATE STATISTICS Anweisung erstellen. Zur Verwaltung eines Indexes werden mehr Systemressourcen benötigt als zur Verwaltung eines Statistikobjekts. Wenn für die Anwendung kein mehrspaltiges Index erforderlich ist, können Sie systemressourcen ökonomisieren, indem Sie das Statistikobjekt erstellen, ohne den Index zu erstellen.
Wenn Sie mehrspaltige Statistiken erstellen, wirkt sich die Reihenfolge der Spalten in der Definition des Statistikobjekts auf die Effektivität von Dichten für die Erstellung von Kardinalitätsschätzungen aus. Im Statistikobjekt werden Dichten für jedes Präfix von Schlüsselspalten in der Statistikobjektdefinition gespeichert. Weitere Informationen zu Densitäten finden Sie im Abschnitt "Dichte " in diesem Artikel.
Zum Erstellen von Dichten, die für Kardinalitätsschätzungen hilfreich sind, müssen die Spalten im Abfrageprädikat einem der Spaltenpräfixe in der Statistikobjektdefinition entsprechen. Im folgenden Beispiel wird beispielsweise aus den Spalten LastName, MiddleNameund FirstName ein Objekt für eine Statistik für mehrere Spalten erstellt.
USE AdventureWorks2022;
GO
IF EXISTS (SELECT name
FROM sys.stats
WHERE name = 'LastFirst'
AND object_ID = OBJECT_ID('Person.Person'))
DROP STATISTICS Person.Person.LastFirst;
GO
CREATE STATISTICS LastFirst
ON Person.Person(LastName, MiddleName, FirstName);
GO
In diesem Beispiel verfügt das Statistikobjekt LastFirst über Dichten für die folgenden Spaltenpräfixe: (LastName), (LastName, MiddleName) und (LastName, MiddleName, FirstName). Die Dichte ist für (LastName, FirstName)nicht verfügbar. Wenn die Abfrage LastName und FirstName verwendet, ohne MiddleNamezu verwenden, ist die Dichte für Kardinalitätsschätzungen nicht verfügbar.
Abfrage wählt aus einer Teilmenge von Daten aus
Wenn der Abfrageoptimierer Statistiken für einzelne Spalten und Indizes erstellt, berechnet er Statistiken für die Werte sämtlicher Zeilen. Wenn bei Abfragen aus einer Teilmenge von Zeilen ausgewählt wird und diese Teilmenge über eine eindeutige Datenverteilung verfügt, können Abfragepläne durch gefilterte Statistiken verbessert werden. Sie können gefilterte Statistiken erstellen, indem Sie die CREATE STATISTICS Anweisung mit der WHERE-Klausel verwenden, um den Filter-Prädikatausdruck zu definieren.
Wenn Sie beispielsweise AdventureWorks2025 verwenden, gehört jedes Produkt in der Production.Product Tabelle zu einer von vier Kategorien in der Production.ProductCategory Tabelle: Bikes, , , ComponentsClothingund Accessories. Jede Kategorie verfügt über eine andere Datenverteilung für das Gewicht: Die Gewichte der Fahrräder reichen von 13,77 bis 30,0, die Gewichte der Bauteile reichen von 2,12 bis 1050,00 mit einigen NULL-Werten, die Gewichte der Bekleidung sind alle NULL, und die Gewichte des Zubehörs sind ebenfalls NULL.
Bei dem Beispiel Bikes liefern gefilterte Statistiken dem Abfrageoptimierer zu allen Fahrradgewichten genauere Statistikdaten und können die Abfrageplanqualität im Vergleich zu Tabellenstatistiken oder nicht vorhandenen Statistiken für die Spalte mit dem Gewicht verbessern. Die Spalte mit dem Fahrradgewicht eignet sich besonders für gefilterte Statistiken, jedoch weniger für einen gefilterten Index, wenn nur relativ wenige Suchen nach Gewichtsangaben ausgeführt werden. Die Leistungsvorteile, die gefilterte Indizes bei der Suche bieten, können die zusätzlichen Kosten für Wartung und Speicher, die mit der Implementierung eines gefilterten Indexes in der Datenbank verbunden sind, jedoch nicht aufwiegen.
Durch die folgende Anweisung wird die gefilterte BikeWeights-Statistik für alle Unterkategorien von Bikes erstellt. Durch den gefilterten Prädikatausdruck werden Fahrräder definiert, indem alle Fahrradunterkategorien mit dem Vergleich Production.ProductSubcategoryID IN (1,2,3)aufgelistet werden. Das Prädikat kann den Bikes Kategorienamen nicht verwenden, da es in der Production.ProductCategory Tabelle gespeichert ist, und alle Spalten im Filterausdruck müssen sich in derselben Tabelle befinden.
USE AdventureWorks2022;
GO
IF EXISTS ( SELECT name FROM sys.stats
WHERE name = 'BikeWeights'
AND object_ID = OBJECT_ID ('Production.Product'))
DROP STATISTICS Production.Product.BikeWeights;
GO
CREATE STATISTICS BikeWeights
ON Production.Product (Weight)
WHERE ProductSubcategoryID IN (1,2,3);
GO
Der Abfrageoptimierer kann die gefilterte Statistik für BikeWeights verwenden, um den Abfrageplan für die folgende Abfrage zu verbessern, bei der alle Fahrräder ausgewählt werden, deren Gewicht größer ist als 25.
SELECT P.Weight AS Weight,
S.Name AS BikeName
FROM Production.Product AS P
INNER JOIN Production.ProductSubcategory AS S
ON P.ProductSubcategoryID = S.ProductSubcategoryID
WHERE P.ProductSubcategoryID IN (1, 2, 3)
AND P.Weight > 25
ORDER BY P.Weight;
GO
Abfrage identifiziert fehlende Statistiken
Wenn der Abfrageoptimierer aufgrund eines Fehlers oder eines anderen Ereignisses keine Statistiken erstellen kann, erstellt er den Abfrageplan ohne Verwendung von Statistiken. Der Abfrageoptimierer kennzeichnet die Statistik als nicht vorhanden und versucht beim nächsten Ausführen der Abfrage, die Statistik erneut zu generieren.
Fehlende Statistiken werden als Warnungen angegeben (Tabellenname als rot formatierter Text), wenn der Ausführungsplan einer Abfrage mithilfe von SQL Server Management Studio grafisch angezeigt wird. Das Fehlen von Statistiken wird zudem angezeigt, wenn die Missing Column Statistics-Ereignisklasse mithilfe von SQL Server Profiler überwacht wird. Weitere Informationen finden Sie unter Fehler und Warnungen-Ereigniskategorie (Datenbank-Engine).
Wenn Statistiken fehlen, führen Sie die folgenden Schritte aus:
- Überprüfen Sie, ob AUTO_CREATE_STATISTICS und AUTO_UPDATE_STATISTICS auf ON gesetzt sind.
- Stellen Sie sicher, dass die Datenbank nicht schreibgeschützt ist. Wenn die Datenbank schreibgeschützt ist, kann kein neues Statistikobjekt gespeichert werden.
- Erstellen Sie die fehlenden Statistiken mithilfe der CREATE STATISTICS Anweisung.
Temporäre Statistiken
Wenn Statistiken zu einer schreibgeschützten Momentaufnahme fehlen oder veraltet sind, erstellt und verwaltet die Datenbank-Engine temporäre Statistiken in tempdb. Wenn die Datenbank-Engine temporäre Statistiken erstellt, wird dem Statistiknamen das Suffix _readonly_database_statistic angefügt, um die temporären Statistiken von den dauerhaften Statistiken zu unterscheiden. Das Suffix _readonly_database_statistic ist für Statistiken reserviert, die vom Datenbankmodul generiert werden. Skripts für die temporären Statistiken können in einer Lese-/Schreibzugriffsdatenbank erstellt und ausgeführt werden. Bei einer Skripterstellung ändert Management Studio das Suffix des Statistiknamens von _readonly_database_statistic in _readonly_database_statistic_scripted.
Nur das Datenbankmodul kann temporäre Statistiken erstellen und aktualisieren. Sie können jedoch temporäre Statistiken löschen und Statistikeigenschaften mit den gleichen Tools überwachen, die Sie für dauerhafte Statistiken verwenden:
- Löschen Sie temporäre Statistiken mithilfe der DROP STATISTICS Anweisung.
- Überwachen Sie Statistiken mit den Katalogsichten sys.stats und sys.stats_columns . Die Systemkatalogansicht
sys.statsbeinhaltet die Spalteis_temporary. Damit wird angegeben, welche Statistiken dauerhaft und welche temporär sind.
Da temporäre Statistiken in tempdb gespeichert werden, entfernt ein Neustart des Datenbankmoduls alle temporären Statistiken.
Genau wie bei allen Statistiken erfordert das Erstellen und Aktualisieren temporärer Statistiken eine Schemaänderung (Sch-M)-Sperre für das Objekt. Diese Sperre blockiert möglicherweise andere Abfragen und Prozesse, einschließlich des Systemredo-Prozesses für sekundäre Replikate, die Transaktionen aus dem primären Replikat anwenden. Wenn sich diese Sperre auf Abfrageworkloads oder Datenverteilung auswirkt, können Sie die automatische Erstellung und Aktualisierung temporärer Statistiken mithilfe der datenbankspezifischen READABLE_SECONDARY_TEMPORARY_STATS_AUTO_CREATE Konfigurationen bzw. READABLE_SECONDARY_TEMPORARY_STATS_AUTO_UPDATEKonfigurationen mit Datenbankbereich deaktivieren.
Gründe für das Aktualisieren von Statistiken
Der Abfrageoptimierer bestimmt, wann Statistiken möglicherweise veraltet sind, und aktualisiert sie dann bei Bedarf für einen Abfrageplan. In einigen Fällen können Sie den Abfrageplan verbessern und somit die Abfrageleistung verbessern, indem Sie Statistiken häufiger aktualisieren, als wenn AUTO_UPDATE_STATISTICS ist ON. Sie können Statistiken mithilfe der UPDATE STATISTICS Anweisung oder der gespeicherten Prozedur sp_updatestatsaktualisieren.
Durch das Update von Statistiken wird sichergestellt, dass Abfragen anhand aktueller Statistiken kompiliert werden. Das Aktualisieren von Statistiken über einen beliebigen Prozess kann dazu führen, dass Abfragepläne automatisch neu kompiliert werden. Aktualisieren Sie Statistiken nicht manuell zu häufig, da es einen Leistungskonflikt zwischen der Verbesserung von Abfrageplänen und der Zeit gibt, die zum Erneuten Kompilieren von Abfragen benötigt wird. Die Entscheidung hängt von der verwendeten Anwendung ab.
Wenn Sie Statistiken mithilfe von UPDATE STATISTICS oder sp_updatestats aktualisieren, lassen Sie AUTO_UPDATE_STATISTICS auf ON festgelegt, damit der Abfrageoptimierer die Statistiken routinemäßig aktualisiert.
Weitere Informationen zum Aktualisieren von Statistiken zu einer Spalte, einem Index, einer Tabelle oder einer indizierten Ansicht finden Sie unter UPDATE STATISTICS.
Informationen zum Aktualisieren von Statistiken für alle benutzerdefinierten und internen Tabellen in der Datenbank finden Sie in der gespeicherten Prozedur sp_updatestats.
Weitere Informationen zu den Schwellenwerten für automatische Statistikupdates finden Sie unter Option AUTO_UPDATE_STATISTICS.
Wenn Sie AUTO_UPDATE_STATISTICS auf OFF festlegen, kann die Planneukompilierung aus verschiedenen anderen Gründen weiterhin auftreten, sie erfolgt jedoch nicht automatisch aufgrund von Aktualisierungen veralteter Statistiken. Wenn Sie AUTO_UPDATE_STATISTICS auf OFF festlegen, erfolgen Statistikaktualisierungen nur durch andere manuell geplante Prozesse, z. B. Wartungspläne. Das Festlegen von AUTO_UPDATE_STATISTICS auf OFF kann daher zu suboptimalen Abfrageplänen und einer beeinträchtigten Abfrageleistung führen.
Erkennen veralteter Statistiken
Um zu ermitteln, wann Statistiken zuletzt aktualisiert wurden, verwenden Sie die Funktionen sys.dm_db_stats_properties oder STATS_DATE.
Ziehen Sie die Aktualisierung von Statistiken unter folgenden Bedingungen in Betracht:
- Die Ausführungszeiten von Abfragen sind langsam.
- Es werden INSERT-Vorgänge für aufsteigend oder absteigend sortierte Schlüsselspalten ausgeführt.
- Eine Wartung wurde durchgeführt.
Beispiele für manuelles Aktualisieren von Statistiken finden Sie unter UPDATE STATISTICS.
Lange Ausführungszeiten für Abfragen
Wenn die Antwortzeiten von Abfragen langsam oder nicht vorhersagbar sind, sollten Sie sicherstellen, dass Abfragen auf aktuelle Statistiken zugreifen, bevor Sie weitere Schritte zur Problembehandlung ausführen.
INSERT-Ausführungen für aufsteigend oder absteigend sortierte Schlüsselspalten
Statistiken zu aufsteigenden oder absteigenden Schlüsselspalten, wie etwa IDENTITY oder Echtzeitzeitstempelspalten, müssen möglicherweise häufiger aktualisiert werden, als der Abfrageoptimierer dies vornimmt. Durch INSERT-Vorgänge werden neue Werte an aufsteigend oder absteigend sortierte Spalten angefügt. Möglicherweise wurden zu wenige Zeilen hinzugefügt, um ein Statistikupdate auszulösen. Wenn Statistiken nicht aktuell sind und bei der Abfrageausführung aus den zuletzt hinzugefügten Zeilen ausgewählt wird, weisen die aktuellen Statistiken keine Kardinalitätsschätzungen für diese neuen Werte auf. Diese Bedingung kann zu ungenauen Kardinalitätsschätzungen und einer langsamen Abfrageleistung führen.
Eine Abfrage, die aus den letzten Verkaufsauftragsterminen auswählt, weist beispielsweise ungenaue Kardinalitätsschätzungen auf, wenn die Statistiken nicht aktualisiert werden, um Kardinalitätsschätzungen für die letzten Verkaufsauftragstermine einzuschließen.
Nach Wartungsvorgängen
Die Aktualisierung von Statistiken empfiehlt sich auch nach dem Durchführen von Wartungsvorgängen, durch die die Verteilung der Daten geändert wird; hierzu gehören z. B. das Abschneiden einer Tabelle oder das Ausführen einer Masseneinfügung für einen großen Prozentsatz von Zeilen. Proaktives Aktualisieren von Statistiken kann zukünftige Verzögerungen bei der Abfrageverarbeitung vermeiden, während Abfragen auf automatische Statistikenaktualisierungen warten.
Vorgänge wie Neuaufbau, Defragmentieren oder Neuorganisieren eines Indexes ändern die Verteilung von Daten nicht. Daher müssen Sie nach der Durchführung ALTER INDEX von REBUILD-, DBCC DBREINDEX-, DBCC INDEXDEFRAG- oder ALTER INDEX REORGANIZE-Vorgängen keine Statistiken aktualisieren. Der Abfrageoptimierer aktualisiert Statistiken, wenn mit ALTER INDEX REBUILD oder DBCC DBREINDEX ein Index für eine Tabelle oder Sicht erstellt wird. Diese Statistikaktualisierung ist jedoch ein Nebenprodukt der Indexneuerstellung. Der Abfrageoptimierer führt keine Statistikaktualisierung nach einem DBCC INDEXDEFRAG- oder ALTER INDEX REORGANIZE-Vorgang aus.
Tip
Verwenden Sie ab SQL Server 2016 (13.x) SP1 CU4 die Option PERSIST_SAMPLE_PERCENT von CREATE STATISTICS oder UPDATE STATISTICS, um einen bestimmten Stichprobenprozentsatz für nachfolgende Statistikaktualisierungen festzulegen und beizubehalten, die keinen Stichprobenprozentsatz explizit angeben.
Automatische Verwaltung von Index und Statistiken
Verwenden Sie Lösungen wie Adaptive Index Defrag, um die Indexdefragmentierung und das Aktualisieren der Statistiken für eine oder mehrere Datenbanken automatisch zu verwalten. Dieses Verfahren wählt anhand des Fragmentierungsgrads und weiterer Parameter automatisch aus, ob ein Index neu erstellt oder neu organisiert werden soll, und aktualisiert Statistiken unter Verwendung eines linearen Schwellenwerts.
Ermitteln der vom Abfrageoptimierer verwendeten Statistiken
Sie finden die Statistikobjekte, die der Abfrageoptimierer beim Kompilieren einer Abfrage verwendet, indem Sie einen geschätzten oder tatsächlichen Ausführungsplan prüfen. Wenn Sie einen Ausführungsplan untersuchen, enthält das Element OptimizerStatsUage Elemente vom Typ StatisticsInfo, die Informationen über die Statistikobjekte enthalten, die der Query Optimizer während der Kompilierung geladen hat. Die StatisticsInfo Elemente enthalten den Namen des Statistikobjekts, die Datenbank, das Schema und die Tabelle, zu der sie gehört, die Änderungsanzahl zur Kompilierungszeit, den Sampling-Prozentsatz und wann sie zuletzt aktualisiert wurde.
Verwenden Sie eine der folgenden Techniken, um den Ausführungsplan zu prüfen:
- Wählen Sie in SQL Server Management Studio vor dem Ausführen der Abfrage die Option Tatsächlichen Ausführungsplan einbeziehen (STRG+M) aus. Auf der Registerkarte "Ausführungsplan ", die mit den Ergebnissen angezeigt wird, können Sie:
- Klicken Sie mit der rechten Maustaste in den grafischen Plan, und wählen Sie "Ausführungsplan-XML anzeigen" aus. Suchen Sie nach dem Element
OptimizerStatsUsageund nach jedem untergeordneten ElementStatisticsInfo. - Wählen Sie den letzten Operator (den ganz linken) aus. (Bei einer
SELECTAbfrage ist dieser Operator einSELECTKnoten.) Erweitern Sie im Eigenschaftenfenster den Knoten OptimizerStatsUsage , und zeigen Sie Informationen zu den in der Abfrage verwendeten Statistikobjekten an.
- Klicken Sie mit der rechten Maustaste in den grafischen Plan, und wählen Sie "Ausführungsplan-XML anzeigen" aus. Suchen Sie nach dem Element
- Führen Sie SETSET STATISTICS XML ON vor der Abfrage aus. Wählen Sie den Link aus, der mit den Ergebnissen angezeigt wird, um den XML-Code für den Ausführungsplan anzuzeigen.
- Abfragen sys.dm_exec_query_plan oder sys.dm_exec_query_statistics_xml für aktuelle Abfragen.
- Lesen Sie einen zuvor erfassten Plan aus Abfragespeicher mithilfe von sys.query_store_plan.
Jedes StatisticsInfo Element sieht wie das folgende XML-Fragment aus einer Abfrage in der AdventureWorks2022 Beispieldatenbank aus:
<StatisticsInfo
Database="[AdventureWorks2022]"
Schema="[Sales]"
Table="[SalesOrderDetail]"
Statistics="[IX_SalesOrderDetail_ProductID]"
ModificationCount="0"
SamplingPercent="100"
LastUpdate="2025-09-07T15:32:16.89" />
| attribute | Bedeutung |
|---|---|
Database, SchemaTable |
Das Objekt, zu dem die Statistik gehört. |
Statistics |
Name des Statistikobjekts in der Datenbank. Verwenden Sie diesen Namen mit DBCC-SHOW_STATISTICS oder sys.stats , um das Histogramm und den Dichtevektor zu untersuchen. |
ModificationCount |
Die Anzahl der Datenänderungen seit der letzten Aktualisierung der Statistik, zum Zeitpunkt der Kompilierung des Plans. Ein großer Wert relativ zur Tabellengröße gibt an, dass die Statistik während der Kompilierung veraltet war. |
SamplingPercent |
Prozentsatz der zum Erstellen der Statistik stichprobenierten Zeilen. Niedrigere Werte können weniger genaue Histogramme für schiefe Daten erzeugen. |
LastUpdate |
Zeitstempel der letzten Statistikaktualisierung. Wenn die Option AUTO_UPDATE_STATISTICS in der Datenbank aktiviert ist, aktualisiert die Datenbank bei Bedarf automatisch Statistiken. |
Note
StatisticsInfo spiegelt Statistiken wider, die während der Plankompilierung verfügbar und berücksichtigt wurden. Wenn ein StatisticsInfo Eintrag für eine Spalte fehlt, für die Ihre Abfragefilter aktiviert sind, hat der Abfrageoptimierer keine relevanten Statistiken identifiziert, was eine potenzielle Quelle für schlechte Leistung ist.
Verwenden Sie sys.dm_db_stats_properties, um die aktuelle Aktualität und Änderungsanzahl für ein Statistikobjekt zu überprüfen. Die folgende Abfrage stellt z. B. die aktuellen Metriken für ein Statistikobjekt bereit, das in der Tabelle IX_SalesOrderDetail_ProductIDbenannt istSales.SalesOrderDetail:
SELECT
OBJECT_SCHEMA_NAME(s.object_id) AS schema_name,
OBJECT_NAME(s.object_id) AS table_name,
s.name AS statistics_name,
sp.last_updated,
sp.rows,
sp.rows_sampled,
sp.modification_counter
FROM sys.stats AS s
OUTER APPLY sys.dm_db_stats_properties(s.object_id, s.stats_id) AS sp
WHERE s.object_id = OBJECT_ID(N'Sales.SalesOrderDetail')
AND s.name = N'IX_SalesOrderDetail_ProductID';
Um zu ermitteln, ob die optionen für die automatische Erstellung und Aktualisierung der aktuellen Datenbank aktiviert sind, verwenden Sie Folgendes:
SELECT [name],
is_auto_create_stats_on,
is_auto_update_stats_on,
is_auto_update_stats_async_on
FROM sys.databases
WHERE [name] = DB_NAME();
Abfragen mit effektiver Verwendung von Statistiken
Bestimmte Abfrageimplementierungen, z. B. lokale Variablen und komplexe Ausdrücke im Abfrageprädikat, können zu suboptimalen Abfrageplänen führen. Um diese Probleme zu vermeiden, befolgen Sie abfrageentwurfsrichtlinien für die effektive Verwendung von Statistiken. Weitere Informationen zu Abfrageprädikaten finden Sie unter Suchbedingung.
Zur Optimierung von Abfrageplänen können Sie Abfrageentwurfsrichtlinien anwenden, die Statistiken effektiv einsetzen, um Kardinalitätsschätzungen für Ausdrücke, Variablen und Funktionen in Abfrageprädikaten zu verbessern. Wenn der Abfrageoptimierer den Wert eines Ausdrucks, einer Variablen oder einer Funktion nicht kennt, weiß er nicht, welcher Wert im Histogramm nachschlagen soll, und kann daher nicht die beste Kardinalitätsschätzung aus dem Histogramm abrufen. Für alle als Stichprobe entnommenen Zeilen im Histogramm verwendet der Abfrageoptimierer stattdessen die durchschnittliche Anzahl von Zeilen pro eindeutigem Wert als Basis für die Kardinalitätsschätzung. Diese Situation führt zu suboptimalen Kardinalitätsschätzungen und kann die Abfrageleistung beeinträchtigen. Weitere Informationen zu Histogrammen finden Sie im Abschnitt "Histogramm " in diesem Artikel oder sys.dm_db_stats_histogram.
In den folgenden Richtlinien wird beschrieben, wie Abfragen geschrieben werden müssen, um Abfragepläne durch optimierte Kardinalitätsschätzungen zu verbessern.
Verbessern der Kardinalitätsschätzungen für Ausdrücke
Um Kardinalitätsschätzungen für Ausdrücke zu verbessern, beachten Sie die folgenden Richtlinien:
- Vereinfachen Sie nach Möglichkeit Ausdrücke, die Konstanten enthalten. Der Abfrageoptimierer wertet nicht alle Funktionen und Ausdrücke aus, die Konstanten enthalten, bevor es Kardinalitätsschätzungen bestimmt. Vereinfachen Sie z.B. den
ABS(-100)-Ausdruck in100. - Wenn der Ausdruck mehrere Variablen verwendet, können Sie in Betracht ziehen, eine berechnete Spalte für den Ausdruck und dann Statistiken oder einen Index für die berechnete Spalte zu erstellen. Das Abfrageprädikat
WHERE PRICE + Tax > 100könnte beispielsweise eine bessere Kardinalitätsschätzung aufweisen, wenn Sie eine berechnete Spalte für den AusdruckPrice + Taxerstellen.
Verbessern der Kardinalitätsschätzungen für Variablen und Funktionen
Um Die Kardinalitätsschätzungen für Variablen und Funktionen zu verbessern, befolgen Sie die folgenden Richtlinien:
Wenn das Abfrageprädikat eine lokale Variable verwendet, könnte das Umschreiben der Abfrage sinnvoll sein, sodass sie statt einer lokalen Variablen einen Parameter verwendet. Der Abfrageoptimierer kennt den Wert einer lokalen Variablen beim Erstellen des Abfrageausführungsplans nicht. Wenn eine Abfrage einen Parameter verwendet, verwendet der Abfrageoptimierer die Kardinalitätsschätzung für den ersten tatsächlichen Parameterwert, den die gespeicherte Prozedur empfängt.
Erwägen Sie die Verwendung einer Standardtabelle oder einer temporären Tabelle, um die Ergebnisse von tabellenwertigen Funktionen mit mehreren Anweisungen zu speichern. Der Abfrageoptimierer erstellt keine Statistiken für tabellenwertige Funktionen mit mehreren Anweisungen. Mit diesem Ansatz kann der Abfrageoptimierer Statistiken zu den Tabellenspalten erstellen und sie verwenden, um einen besseren Abfrageplan zu erstellen.
Standardtabellen oder temporäre Tabelle können auch als Ersatz für Tabellenvariablen verwendet werden. Der Abfrageoptimierer erstellt keine Statistiken für Tabellenvariablen. Mit diesem Ansatz kann der Abfrageoptimierer Statistiken zu den Tabellenspalten erstellen und sie verwenden, um einen besseren Abfrageplan zu erstellen. Es gibt Kompromisse bei der Bestimmung, ob eine temporäre Tabelle oder eine Tabellenvariable verwendet werden soll. Tabellenvariablen, die in gespeicherten Prozeduren verwendet werden, verursachen weniger Neukompilierungen der gespeicherten Prozedur als temporäre Tabellen. Nicht bei allen Anwendungen wird die Leistung optimiert, wenn statt einer Tabellenvariablen eine temporäre Tabelle verwendet wird.
Wenn eine gespeicherte Prozedur eine Abfrage enthält, die einen übergebenen Parameter verwendet, sollten Sie den Parameterwert innerhalb der gespeicherten Prozedur nicht ändern, bevor Sie ihn in der Abfrage verwenden. Die Kardinalitätsschätzungen für die Abfrage basieren auf dem übergebenen Parameterwert und nicht auf dem aktualisierten Wert. Damit der Parameterwert nicht geändert werden kann, können Sie die Abfrage so umschreiben, dass zwei gespeicherte Prozeduren verwendet werden.
Durch die folgende gespeicherte Prozedur
Sales.GetRecentSaleswird beispielsweise der Wert des Parameters@dategeändert, wenn@dateaufNULLfestgelegt ist.USE AdventureWorks2022; GO IF OBJECT_ID('Sales.GetRecentSales', 'P') IS NOT NULL DROP PROCEDURE Sales.GetRecentSales; GO CREATE PROCEDURE Sales.GetRecentSales @date DATETIME AS BEGIN IF @date IS NULL SET @date = DATEADD(MONTH, -3, (SELECT MAX(ORDERDATE) FROM Sales.SalesOrderHeader)); SELECT * FROM Sales.SalesOrderHeader AS h, Sales.SalesOrderDetail AS d WHERE h.SalesOrderID = d.SalesOrderID AND h.OrderDate > @date; END GOWenn der erste Aufruf der gespeicherten Prozedur
Sales.GetRecentSaleseineNULLfür den Parameter@dateübergibt, kompiliert der Abfrageoptimierer die gespeicherte Prozedur mit der Kardinalitätsschätzung für@date = NULL, obwohl das Abfrageprädikat nicht mit@date = NULLaufgerufen wird. Diese Kardinalitätsschätzung unterscheidet sich möglicherweise erheblich von der Anzahl der Zeilen im tatsächlichen Abfrageergebnis. Folglich könnte der Abfrageoptimierer einen suboptimalen Abfrageplan auswählen. Um dieses Problem zu vermeiden, können Sie die gespeicherte Prozedur wie folgt in zwei Prozeduren umschreiben:USE AdventureWorks2022; GO IF OBJECT_ID('Sales.GetNullRecentSales', 'P') IS NOT NULL DROP PROCEDURE Sales.GetNullRecentSales; GO CREATE PROCEDURE Sales.GetNullRecentSales @date DATETIME AS BEGIN IF @date IS NULL SET @date = DATEADD(MONTH, -3, (SELECT MAX(ORDERDATE) FROM Sales.SalesOrderHeader)); EXECUTE Sales.GetNonNullRecentSales @date; END GO IF OBJECT_ID('Sales.GetNonNullRecentSales', 'P') IS NOT NULL DROP PROCEDURE Sales.GetNonNullRecentSales; GO CREATE PROCEDURE Sales.GetNonNullRecentSales @date DATETIME AS BEGIN SELECT * FROM Sales.SalesOrderHeader AS h, Sales.SalesOrderDetail AS d WHERE h.SalesOrderID = d.SalesOrderID AND h.OrderDate > @date; END GO
Verbessern der Kardinalitätsschätzungen mit Abfragehinweisen
Zur Verbesserung der Kardinalitätsschätzungen für lokale Variablen verwenden Sie die Abfragehinweise OPTIMIZE FOR <value> oder OPTIMIZE FOR UNKNOWN mit RECOMPILE. Weitere Informationen finden Sie unter Abfragehinweise.
Bei einigen Anwendungen könnte es zu lange dauern, die Abfrage bei jeder Ausführung neu zu kompilieren. Der OPTIMIZE FOR-Abfragehinweis kann selbst dann hilfreich sein, wenn Sie die RECOMPILE-Option nicht verwenden. Sie können der gespeicherten OPTIMIZE FOR-Prozedur z. B. eine Sales.GetRecentSales-Option hinzufügen, um ein bestimmtes Datum anzugeben. Im folgenden Beispiel wird der OPTIMIZE FOR-Prozedur die Sales.GetRecentSales-Option hinzugefügt.
USE AdventureWorks2022;
GO
IF OBJECT_ID('Sales.GetRecentSales', 'P') IS NOT NULL
DROP PROCEDURE Sales.GetRecentSales;
GO
CREATE PROCEDURE Sales.GetRecentSales
@date DATETIME
AS
BEGIN
IF @date IS NULL
SET @date = DATEADD(MONTH, -3,
(SELECT MAX(ORDERDATE)
FROM Sales.SalesOrderHeader));
SELECT *
FROM Sales.SalesOrderHeader AS h, Sales.SalesOrderDetail AS d
WHERE h.SalesOrderID = d.SalesOrderID AND h.OrderDate > @date
OPTION (OPTIMIZE FOR (@date = '2004-05-01 00:00:00.000'));
END
GO
Verbessern der Kardinalitätsschätzungen mit Planhinweislisten
Bei einigen Anwendungen gelten möglicherweise keine Abfrageentwurfsrichtlinien, da Sie die Abfrage nicht ändern können oder der RECOMPILE Abfragehinweis zu vielen Neukompilierungen führen kann. Verwenden Sie Planleitfäden, um weitere Hinweise wie USE PLAN anzugeben und so das Verhalten der Abfrage zu steuern, während Sie gemeinsam mit dem Anwendungsanbieter Änderungen an der Anwendung untersuchen. Weitere Informationen zu Planhinweislisten finden Sie unter Planhinweislisten.
Ziehen Sie in Azure SQL-Datenbank zum Erzwingen von Plänen anstelle von Planhinweislisten Abfragespeicherhinweise in Betracht. Weitere Informationen finden Sie unter Abfragespeicherhinweise.
Verwandte Inhalte
- Statistiken für speicheroptimierte Tabellen
- CREATE STATISTICS (Transact-SQL)
- UPDATE UPDATE STATISTICS (Transact-SQL)
- sp_updatestats (Transact-SQL)
- DBCC-SHOW_STATISTICS (Transact-SQL)
- ALTER DATABASE SET Optionen (Transact-SQL)
- DROP STATISTICS (Transact-SQL)
- CREATE INDEX (Transact-SQL)
- ALTER INDEX (Transact-SQL)
- Gefilterte Indizes erstellen
- STATS_DATE (Transact-SQL)
- sys.dm_db_stats_properties (Transact-SQL)
- sys.dm_db_stats_histogram (Transact-SQL)
- sys.stats
- sys.stats_columns (Transact-SQL)
- Adaptive Indexdefragmentierung